cherry-pick.softflowd-0.9.9-5-gb4a7a1c.tos-field-is-metered-and-exported-in-netflow-v1-v5-v9-and-ipfix-in-default-settings.patch 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. Subject: ToS field is metered and exported in NetFlow v1,v5,v9 and IPFIX in default settings
  2. Origin: softflowd-0.9.9-5-gb4a7a1c <https://github.com/irino/softflowd/commit/softflowd-0.9.9-5-gb4a7a1c>
  3. Upstream-Author: Hitoshi Irino <hitoshi.irino@gmail.com>
  4. Date: Sun Dec 23 23:44:10 2012 +0900
  5. -A option is added for exporting absolute time field in IPFIX records to be able to receive with NFDUMP(nfcapd).
  6. -P option is added to select export transport protocol from UDP, TCP, and SCTP. (It is not tested yet.)
  7. --- a/configure.ac
  8. +++ b/configure.ac
  9. @@ -52,6 +52,7 @@
  10. [ AC_DEFINE_UNQUOTED([PRIVDROP_CHROOT_DIR], ["${withval}"], [privdrop chroot directory]) ]
  11. )
  12. +AC_DEFINE([_BSD_SOURCE], [], [Define BSD SOURCE for Linux])
  13. AC_CHECK_HEADERS(net/bpf.h pcap.h pcap-bpf.h sys/endian.h endian.h)
  14. dnl AC_CHECK_HEADERS(netinet/in_systm.h netinet/tcp.h netinet/udp.h)
  15. --- a/ipfix.c
  16. +++ b/ipfix.c
  17. @@ -28,6 +28,11 @@
  18. #include "treetype.h"
  19. #include "softflowd.h"
  20. +#if defined (HAVE_HTONLL) && !defined (HAVE_HTOBE64)
  21. +#define htobe64 htonll
  22. +#endif
  23. +#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
  24. +
  25. /* IPFIX a.k.a. Netflow v.10 */
  26. struct IPFIX_HEADER {
  27. u_int16_t version, length;
  28. @@ -62,6 +67,7 @@
  29. #define IPFIX_packetDeltaCount 2
  30. /* ... */
  31. #define IPFIX_protocolIdentifier 4
  32. +#define IPFIX_ipClassOfService 5
  33. /* ... */
  34. #define IPFIX_tcpControlBits 6
  35. #define IPFIX_sourceTransportPort 7
  36. @@ -77,12 +83,23 @@
  37. #define IPFIX_flowStartSysUpTime 22
  38. /* ... */
  39. #define IPFIX_sourceIPv6Address 27
  40. -#define IPFIX_destinationIPv6Address 28
  41. +#define IPFIX_destinationIPv6Address 28
  42. +/* ... */
  43. +#define IPFIX_ipVersion 60
  44. /* ... */
  45. -#define IPFIX_ipVersion 60
  46. -
  47. #define IPFIX_meteringProcessId 143
  48. +/* ... */
  49. +#define IPFIX_flowStartSeconds 150
  50. +#define IPFIX_flowEndSeconds 151
  51. +#define IPFIX_flowStartMilliSeconds 152
  52. +#define IPFIX_flowEndMilliSeconds 153
  53. +#define IPFIX_flowStartMicroSeconds 154
  54. +#define IPFIX_flowEndMicroSeconds 155
  55. +#define IPFIX_flowStartNanoSeconds 156
  56. +#define IPFIX_flowEndNanoSeconds 157
  57. +/* ... */
  58. #define IPFIX_systemInitTimeMilliseconds 160
  59. +/* ... */
  60. #define PSAMP_selectorAlgorithm 304
  61. #define PSAMP_samplingPacketInterval 305
  62. #define PSAMP_samplingPacketSpace 306
  63. @@ -90,7 +107,7 @@
  64. #define PSAMP_selectorAlgorithm_count 1
  65. /* Stuff pertaining to the templates that softflowd uses */
  66. -#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 13
  67. +#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 14
  68. struct IPFIX_SOFTFLOWD_TEMPLATE {
  69. struct IPFIX_TEMPLATE_SET_HEADER h;
  70. struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS];
  71. @@ -106,22 +123,35 @@
  72. /* softflowd data set */
  73. struct IPFIX_SOFTFLOWD_DATA_COMMON {
  74. - u_int32_t flowEndSysUpTime, flowStartSysUpTime;
  75. u_int32_t octetDeltaCount, packetDeltaCount;
  76. u_int32_t ingressInterface, egressInterface;
  77. u_int16_t sourceTransportPort, destinationTransportPort;
  78. - u_int8_t protocolIdentifier, tcpControlBits, ipVersion;
  79. + u_int8_t protocolIdentifier, tcpControlBits, ipVersion, ipClassOfService;
  80. + //u_int32_t flowEndSysUpTime, flowStartSysUpTime;
  81. } __packed;
  82. +union IPFIX_SOFTFLOWD_DATA_TIME {
  83. + struct {
  84. + u_int32_t start;
  85. + u_int32_t end;
  86. + } u32;
  87. + struct {
  88. + u_int64_t start;
  89. + u_int64_t end;
  90. + } u64;
  91. +};
  92. +
  93. struct IPFIX_SOFTFLOWD_DATA_V4 {
  94. u_int32_t sourceIPv4Address, destinationIPv4Address;
  95. struct IPFIX_SOFTFLOWD_DATA_COMMON c;
  96. + union IPFIX_SOFTFLOWD_DATA_TIME t;
  97. } __packed;
  98. struct IPFIX_SOFTFLOWD_DATA_V6 {
  99. //u_int8_t src_addr[16], dst_addr[16];
  100. struct in6_addr sourceIPv6Address, destinationIPv6Address;
  101. struct IPFIX_SOFTFLOWD_DATA_COMMON c;
  102. + union IPFIX_SOFTFLOWD_DATA_TIME t;
  103. } __packed;
  104. struct IPFIX_SOFTFLOWD_OPTION_DATA {
  105. @@ -159,7 +189,7 @@
  106. static int ipfix_pkts_until_template = -1;
  107. static void
  108. -ipfix_init_template(void)
  109. +ipfix_init_template(struct FLOWTRACKPARAMETERS *param)
  110. {
  111. bzero(&v4_template, sizeof(v4_template));
  112. v4_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
  113. @@ -170,28 +200,52 @@
  114. v4_template.r[0].length = htons(4);
  115. v4_template.r[1].ie = htons(IPFIX_destinationIPv4Address);
  116. v4_template.r[1].length = htons(4);
  117. - v4_template.r[2].ie = htons(IPFIX_flowEndSysUpTime);
  118. + v4_template.r[2].ie = htons(IPFIX_octetDeltaCount);
  119. v4_template.r[2].length = htons(4);
  120. - v4_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
  121. + v4_template.r[3].ie = htons(IPFIX_packetDeltaCount);
  122. v4_template.r[3].length = htons(4);
  123. - v4_template.r[4].ie = htons(IPFIX_octetDeltaCount);
  124. + v4_template.r[4].ie = htons(IPFIX_ingressInterface);
  125. v4_template.r[4].length = htons(4);
  126. - v4_template.r[5].ie = htons(IPFIX_packetDeltaCount);
  127. + v4_template.r[5].ie = htons(IPFIX_egressInterface);
  128. v4_template.r[5].length = htons(4);
  129. - v4_template.r[6].ie = htons(IPFIX_ingressInterface);
  130. - v4_template.r[6].length = htons(4);
  131. - v4_template.r[7].ie = htons(IPFIX_egressInterface);
  132. - v4_template.r[7].length = htons(4);
  133. - v4_template.r[8].ie = htons(IPFIX_sourceTransportPort);
  134. - v4_template.r[8].length = htons(2);
  135. - v4_template.r[9].ie = htons(IPFIX_destinationTransportPort);
  136. - v4_template.r[9].length = htons(2);
  137. - v4_template.r[10].ie = htons(IPFIX_protocolIdentifier);
  138. + v4_template.r[6].ie = htons(IPFIX_sourceTransportPort);
  139. + v4_template.r[6].length = htons(2);
  140. + v4_template.r[7].ie = htons(IPFIX_destinationTransportPort);
  141. + v4_template.r[7].length = htons(2);
  142. + v4_template.r[8].ie = htons(IPFIX_protocolIdentifier);
  143. + v4_template.r[8].length = htons(1);
  144. + v4_template.r[9].ie = htons(IPFIX_tcpControlBits);
  145. + v4_template.r[9].length = htons(1);
  146. + v4_template.r[10].ie = htons(IPFIX_ipVersion);
  147. v4_template.r[10].length = htons(1);
  148. - v4_template.r[11].ie = htons(IPFIX_tcpControlBits);
  149. + v4_template.r[11].ie = htons(IPFIX_ipClassOfService);
  150. v4_template.r[11].length = htons(1);
  151. - v4_template.r[12].ie = htons(IPFIX_ipVersion);
  152. - v4_template.r[12].length = htons(1);
  153. + if (param->time_format == 's') {
  154. + v4_template.r[12].ie = htons(IPFIX_flowStartSeconds);
  155. + v4_template.r[12].length = htons(sizeof(u_int32_t));
  156. + v4_template.r[13].ie = htons(IPFIX_flowEndSeconds);
  157. + v4_template.r[13].length = htons(sizeof(u_int32_t));
  158. + } else if (param->time_format == 'm') {
  159. + v4_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
  160. + v4_template.r[12].length = htons(sizeof(u_int64_t));
  161. + v4_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
  162. + v4_template.r[13].length = htons(sizeof(u_int64_t));
  163. + } else if (param->time_format == 'M') {
  164. + v4_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
  165. + v4_template.r[12].length = htons(sizeof(u_int64_t));
  166. + v4_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
  167. + v4_template.r[13].length = htons(sizeof(u_int64_t));
  168. + } else if (param->time_format == 'n') {
  169. + v4_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
  170. + v4_template.r[12].length = htons(sizeof(u_int64_t));
  171. + v4_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
  172. + v4_template.r[13].length = htons(sizeof(u_int64_t));
  173. + } else {
  174. + v4_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
  175. + v4_template.r[12].length = htons(sizeof(u_int32_t));
  176. + v4_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
  177. + v4_template.r[13].length = htons(sizeof(u_int32_t));
  178. + }
  179. bzero(&v6_template, sizeof(v6_template));
  180. v6_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
  181. @@ -202,28 +256,52 @@
  182. v6_template.r[0].length = htons(16);
  183. v6_template.r[1].ie = htons(IPFIX_destinationIPv6Address);
  184. v6_template.r[1].length = htons(16);
  185. - v6_template.r[2].ie = htons(IPFIX_flowEndSysUpTime);
  186. + v6_template.r[2].ie = htons(IPFIX_octetDeltaCount);
  187. v6_template.r[2].length = htons(4);
  188. - v6_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
  189. + v6_template.r[3].ie = htons(IPFIX_packetDeltaCount);
  190. v6_template.r[3].length = htons(4);
  191. - v6_template.r[4].ie = htons(IPFIX_octetDeltaCount);
  192. + v6_template.r[4].ie = htons(IPFIX_ingressInterface);
  193. v6_template.r[4].length = htons(4);
  194. - v6_template.r[5].ie = htons(IPFIX_packetDeltaCount);
  195. + v6_template.r[5].ie = htons(IPFIX_egressInterface);
  196. v6_template.r[5].length = htons(4);
  197. - v6_template.r[6].ie = htons(IPFIX_ingressInterface);
  198. - v6_template.r[6].length = htons(4);
  199. - v6_template.r[7].ie = htons(IPFIX_egressInterface);
  200. - v6_template.r[7].length = htons(4);
  201. - v6_template.r[8].ie = htons(IPFIX_sourceTransportPort);
  202. - v6_template.r[8].length = htons(2);
  203. - v6_template.r[9].ie = htons(IPFIX_destinationTransportPort);
  204. - v6_template.r[9].length = htons(2);
  205. - v6_template.r[10].ie = htons(IPFIX_protocolIdentifier);
  206. + v6_template.r[6].ie = htons(IPFIX_sourceTransportPort);
  207. + v6_template.r[6].length = htons(2);
  208. + v6_template.r[7].ie = htons(IPFIX_destinationTransportPort);
  209. + v6_template.r[7].length = htons(2);
  210. + v6_template.r[8].ie = htons(IPFIX_protocolIdentifier);
  211. + v6_template.r[8].length = htons(1);
  212. + v6_template.r[9].ie = htons(IPFIX_tcpControlBits);
  213. + v6_template.r[9].length = htons(1);
  214. + v6_template.r[10].ie = htons(IPFIX_ipVersion);
  215. v6_template.r[10].length = htons(1);
  216. - v6_template.r[11].ie = htons(IPFIX_tcpControlBits);
  217. + v6_template.r[11].ie = htons(IPFIX_ipClassOfService);
  218. v6_template.r[11].length = htons(1);
  219. - v6_template.r[12].ie = htons(IPFIX_ipVersion);
  220. - v6_template.r[12].length = htons(1);
  221. + if (param->time_format == 's') {
  222. + v6_template.r[12].ie = htons(IPFIX_flowStartSeconds);
  223. + v6_template.r[12].length = htons(sizeof(u_int32_t));
  224. + v6_template.r[13].ie = htons(IPFIX_flowEndSeconds);
  225. + v6_template.r[13].length = htons(sizeof(u_int32_t));
  226. + } else if (param->time_format == 'm') {
  227. + v6_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
  228. + v6_template.r[12].length = htons(sizeof(u_int64_t));
  229. + v6_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
  230. + v6_template.r[13].length = htons(sizeof(u_int64_t));
  231. + } else if (param->time_format == 'M') {
  232. + v6_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
  233. + v6_template.r[12].length = htons(sizeof(u_int64_t));
  234. + v6_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
  235. + v6_template.r[13].length = htons(sizeof(u_int64_t));
  236. + } else if (param->time_format == 'n') {
  237. + v6_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
  238. + v6_template.r[12].length = htons(sizeof(u_int64_t));
  239. + v6_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
  240. + v6_template.r[13].length = htons(sizeof(u_int64_t));
  241. + } else {
  242. + v6_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
  243. + v6_template.r[12].length = htons(sizeof(u_int32_t));
  244. + v6_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
  245. + v6_template.r[13].length = htons(sizeof(u_int32_t));
  246. + }
  247. }
  248. static void
  249. @@ -249,10 +327,8 @@
  250. option_data.c.set_id = htons(IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
  251. option_data.c.length = htons(sizeof(option_data));
  252. option_data.scope_pid = htonl((u_int32_t)option->meteringProcessId);
  253. -#if defined HAVE_HTOBE64
  254. +#if defined (_BSD_SOURCE) && defined (HAVE_ENDIAN_H) || defined (HAVE_HTOBE64) || defined (HAVE_HTONLL)
  255. option_data.systemInitTimeMilliseconds = htobe64((u_int64_t)system_boot_time->tv_sec * 1000 + (u_int64_t)system_boot_time->tv_usec / 1000);
  256. -#elif defined HAVE_HTONLL
  257. - option_data.systemInitTimeMilliseconds = htonll((u_int64_t)system_boot_time->tv_sec * 1000 + (u_int64_t)system_boot_time->tv_usec / 1000);
  258. #endif
  259. option_data.samplingAlgorithm = htons(PSAMP_selectorAlgorithm_count);
  260. option_data.samplingInterval = htons(1);
  261. @@ -260,13 +336,15 @@
  262. }
  263. static int
  264. ipfix_flow_to_flowset(const struct FLOW *flow, u_char *packet, u_int len,
  265. - u_int16_t ifidx, const struct timeval *system_boot_time, u_int *len_used)
  266. + u_int16_t ifidx, const struct timeval *system_boot_time, u_int *len_used,
  267. + struct FLOWTRACKPARAMETERS *param)
  268. {
  269. union {
  270. struct IPFIX_SOFTFLOWD_DATA_V4 d4;
  271. struct IPFIX_SOFTFLOWD_DATA_V6 d6;
  272. } d[2];
  273. struct IPFIX_SOFTFLOWD_DATA_COMMON *dc[2];
  274. + union IPFIX_SOFTFLOWD_DATA_TIME *dt[2];
  275. u_int freclen, ret_len, nflows;
  276. bzero(d, sizeof(d));
  277. @@ -274,32 +352,68 @@
  278. switch (flow->af) {
  279. case AF_INET:
  280. freclen = sizeof(struct IPFIX_SOFTFLOWD_DATA_V4);
  281. + if (!(param->time_format == 'm' || param->time_format == 'M' || param->time_format == 'n')) {
  282. + freclen -= (sizeof(u_int64_t) - sizeof(u_int32_t)) * 2;
  283. + }
  284. memcpy(&d[0].d4.sourceIPv4Address, &flow->addr[0].v4, 4);
  285. memcpy(&d[0].d4.destinationIPv4Address, &flow->addr[1].v4, 4);
  286. memcpy(&d[1].d4.sourceIPv4Address, &flow->addr[1].v4, 4);
  287. memcpy(&d[1].d4.destinationIPv4Address, &flow->addr[0].v4, 4);
  288. dc[0] = &d[0].d4.c;
  289. dc[1] = &d[1].d4.c;
  290. + dt[0] = &d[0].d4.t;
  291. + dt[1] = &d[1].d4.t;
  292. dc[0]->ipVersion = dc[1]->ipVersion = 4;
  293. break;
  294. case AF_INET6:
  295. freclen = sizeof(struct IPFIX_SOFTFLOWD_DATA_V6);
  296. + if (!(param->time_format == 'm' || param->time_format == 'M' || param->time_format == 'n')) {
  297. + freclen -= (sizeof(u_int64_t) - sizeof(u_int32_t)) * 2;
  298. + }
  299. memcpy(&d[0].d6.sourceIPv6Address, &flow->addr[0].v6, 16);
  300. memcpy(&d[0].d6.destinationIPv6Address, &flow->addr[1].v6, 16);
  301. memcpy(&d[1].d6.sourceIPv6Address, &flow->addr[1].v6, 16);
  302. memcpy(&d[1].d6.destinationIPv6Address, &flow->addr[0].v6, 16);
  303. dc[0] = &d[0].d6.c;
  304. dc[1] = &d[1].d6.c;
  305. + dt[0] = &d[0].d6.t;
  306. + dt[1] = &d[1].d6.t;
  307. dc[0]->ipVersion = dc[1]->ipVersion = 6;
  308. break;
  309. default:
  310. return (-1);
  311. }
  312. - dc[0]->flowStartSysUpTime = dc[1]->flowStartSysUpTime =
  313. - htonl(timeval_sub_ms(&flow->flow_start, system_boot_time));
  314. - dc[0]->flowEndSysUpTime = dc[1]->flowEndSysUpTime =
  315. - htonl(timeval_sub_ms(&flow->flow_last, system_boot_time));
  316. + if (param->time_format == 's') {
  317. + dt[0]->u32.start = dt[1]->u32.start =
  318. + htonl(flow->flow_start.tv_sec);
  319. + dt[0]->u32.end = dt[1]->u32.end =
  320. + htonl(flow->flow_last.tv_sec);
  321. + }
  322. +#if defined (_BSD_SOURCE) && defined (HAVE_ENDIAN_H) || defined (HAVE_HTOBE64) || defined (HAVE_HTONLL)
  323. + else if (param->time_format == 'm') { /* milliseconds */
  324. + dt[0]->u64.start = dt[1]->u64.start =
  325. + htobe64((u_int64_t)flow->flow_start.tv_sec * 1000 + (u_int64_t)flow->flow_start.tv_usec / 1000);
  326. + dt[0]->u64.end = dt[1]->u64.end =
  327. + htobe64((u_int64_t)flow->flow_last.tv_sec * 1000 + (u_int64_t)flow->flow_last.tv_usec / 1000);
  328. + } else if (param->time_format == 'M') { /* microseconds */
  329. + dt[0]->u64.start = dt[1]->u64.start =
  330. + htobe64(((u_int64_t)(flow->flow_start.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec << 32)/ 1e6));
  331. + dt[0]->u64.end = dt[1]->u64.end =
  332. + htobe64(((u_int64_t)(flow->flow_last.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec << 32)/ 1e6));
  333. + } else if (param->time_format == 'n') { /* nanoseconds */
  334. + dt[0]->u64.start = dt[1]->u64.start =
  335. + htobe64(((u_int64_t)(flow->flow_start.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec * 1000 << 32)/ 1e9));
  336. + dt[0]->u64.end = dt[1]->u64.end =
  337. + htobe64(((u_int64_t)(flow->flow_last.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec * 1000 << 32)/ 1e9));
  338. + }
  339. +#endif
  340. + else {
  341. + dt[0]->u32.start = dt[1]->u32.start =
  342. + htonl(timeval_sub_ms(&flow->flow_start, system_boot_time));
  343. + dt[0]->u32.end = dt[1]->u32.end =
  344. + htonl(timeval_sub_ms(&flow->flow_last, system_boot_time));
  345. + }
  346. dc[0]->octetDeltaCount = htonl(flow->octets[0]);
  347. dc[1]->octetDeltaCount = htonl(flow->octets[1]);
  348. dc[0]->packetDeltaCount = htonl(flow->packets[0]);
  349. @@ -311,6 +425,8 @@
  350. dc[0]->protocolIdentifier = dc[1]->protocolIdentifier = flow->protocol;
  351. dc[0]->tcpControlBits = flow->tcp_flags[0];
  352. dc[1]->tcpControlBits = flow->tcp_flags[1];
  353. + dc[0]->ipClassOfService = flow->tos[0];
  354. + dc[1]->ipClassOfService = flow->tos[1];
  355. if (flow->octets[0] > 0) {
  356. if (ret_len + freclen > len)
  357. @@ -355,7 +471,7 @@
  358. gettimeofday(&now, NULL);
  359. if (ipfix_pkts_until_template == -1) {
  360. - ipfix_init_template();
  361. + ipfix_init_template(param);
  362. ipfix_pkts_until_template = 0;
  363. if (option != NULL){
  364. ipfix_init_option(system_boot_time, option);
  365. @@ -424,7 +540,7 @@
  366. }
  367. r = ipfix_flow_to_flowset(flows[i + j], packet + offset,
  368. - sizeof(packet) - offset, ifidx, system_boot_time, &inc);
  369. + sizeof(packet) - offset, ifidx, system_boot_time, &inc, param);
  370. if (r <= 0) {
  371. /* yank off data header, if we had to go back */
  372. if (last_valid)
  373. --- a/netflow1.c
  374. +++ b/netflow1.c
  375. @@ -123,6 +123,7 @@
  376. system_boot_time));
  377. flw->protocol = flows[i]->protocol;
  378. flw->tcp_flags = flows[i]->tcp_flags[0];
  379. + flw->tos = flows[i]->tos[0];
  380. offset += sizeof(*flw);
  381. j++;
  382. hdr->flows++;
  383. @@ -145,6 +146,7 @@
  384. system_boot_time));
  385. flw->protocol = flows[i]->protocol;
  386. flw->tcp_flags = flows[i]->tcp_flags[1];
  387. + flw->tos = flows[i]->tos[1];
  388. offset += sizeof(*flw);
  389. j++;
  390. hdr->flows++;
  391. --- a/netflow5.c
  392. +++ b/netflow5.c
  393. @@ -128,6 +128,7 @@
  394. system_boot_time));
  395. flw->tcp_flags = flows[i]->tcp_flags[0];
  396. flw->protocol = flows[i]->protocol;
  397. + flw->tos = flows[i]->tos[0];
  398. offset += sizeof(*flw);
  399. j++;
  400. hdr->flows++;
  401. @@ -151,6 +152,7 @@
  402. system_boot_time));
  403. flw->tcp_flags = flows[i]->tcp_flags[1];
  404. flw->protocol = flows[i]->protocol;
  405. + flw->tos = flows[i]->tos[1];
  406. offset += sizeof(*flw);
  407. j++;
  408. hdr->flows++;
  409. --- a/netflow9.c
  410. +++ b/netflow9.c
  411. @@ -58,7 +58,8 @@
  412. #define NF9_IN_BYTES 1
  413. #define NF9_IN_PACKETS 2
  414. /* ... */
  415. -#define NF9_IN_PROTOCOL 4
  416. +#define NF9_PROTOCOL 4
  417. +#define NF9_TOS 5
  418. /* ... */
  419. #define NF9_TCP_FLAGS 6
  420. #define NF9_L4_SRC_PORT 7
  421. @@ -102,7 +103,7 @@
  422. u_int32_t bytes, packets;
  423. u_int32_t if_index_in, if_index_out;
  424. u_int16_t src_port, dst_port;
  425. - u_int8_t protocol, tcp_flags, ipproto;
  426. + u_int8_t protocol, tcp_flags, ipproto, tos;
  427. } __packed;
  428. struct NF9_SOFTFLOWD_DATA_V4 {
  429. @@ -176,12 +177,14 @@
  430. v4_template.r[8].length = htons(2);
  431. v4_template.r[9].type = htons(NF9_L4_DST_PORT);
  432. v4_template.r[9].length = htons(2);
  433. - v4_template.r[10].type = htons(NF9_IN_PROTOCOL);
  434. + v4_template.r[10].type = htons(NF9_PROTOCOL);
  435. v4_template.r[10].length = htons(1);
  436. v4_template.r[11].type = htons(NF9_TCP_FLAGS);
  437. v4_template.r[11].length = htons(1);
  438. v4_template.r[12].type = htons(NF9_IP_PROTOCOL_VERSION);
  439. v4_template.r[12].length = htons(1);
  440. + v4_template.r[13].type = htons(NF9_TOS);
  441. + v4_template.r[13].length = htons(1);
  442. bzero(&v6_template, sizeof(v6_template));
  443. v6_template.h.c.flowset_id = htons(NF9_TEMPLATE_FLOWSET_ID);
  444. @@ -208,12 +211,14 @@
  445. v6_template.r[8].length = htons(2);
  446. v6_template.r[9].type = htons(NF9_L4_DST_PORT);
  447. v6_template.r[9].length = htons(2);
  448. - v6_template.r[10].type = htons(NF9_IN_PROTOCOL);
  449. + v6_template.r[10].type = htons(NF9_PROTOCOL);
  450. v6_template.r[10].length = htons(1);
  451. v6_template.r[11].type = htons(NF9_TCP_FLAGS);
  452. v6_template.r[11].length = htons(1);
  453. v6_template.r[12].type = htons(NF9_IP_PROTOCOL_VERSION);
  454. v6_template.r[12].length = htons(1);
  455. + v6_template.r[13].type = htons(NF9_TOS);
  456. + v6_template.r[13].length = htons(1);
  457. }
  458. static void
  459. @@ -291,6 +296,8 @@
  460. dc[0]->protocol = dc[1]->protocol = flow->protocol;
  461. dc[0]->tcp_flags = flow->tcp_flags[0];
  462. dc[1]->tcp_flags = flow->tcp_flags[1];
  463. + dc[0]->tos = flow->tos[0];
  464. + dc[1]->tos = flow->tos[1];
  465. if (flow->octets[0] > 0) {
  466. if (ret_len + freclen > len)
  467. --- a/softflowd.c
  468. +++ b/softflowd.c
  469. @@ -1271,7 +1271,7 @@
  470. }
  471. static int
  472. -connsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit)
  473. +connsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit, int protocol)
  474. {
  475. int s;
  476. unsigned int h6;
  477. @@ -1279,7 +1279,7 @@
  478. struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
  479. struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
  480. - if ((s = socket(addr->ss_family, SOCK_DGRAM, 0)) == -1) {
  481. + if ((s = socket(addr->ss_family, protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, protocol)) == -1) {
  482. fprintf(stderr, "socket() error: %s\n",
  483. strerror(errno));
  484. exit(1);
  485. @@ -1486,24 +1486,28 @@
  486. fprintf(stderr,
  487. "Usage: %s [options] [bpf_program]\n"
  488. "This is %s version %s. Valid commandline options:\n"
  489. -" -i [idx:]interface Specify interface to listen on\n"
  490. -" -r pcap_file Specify packet capture file to read\n"
  491. -" -t timeout=time Specify named timeout\n"
  492. -" -m max_flows Specify maximum number of flows to track (default %d)\n"
  493. -" -n host:port Send Cisco NetFlow(tm)-compatible packets to host:port\n"
  494. -" -p pidfile Record pid in specified file\n"
  495. -" (default: %s)\n"
  496. -" -c pidfile Location of control socket\n"
  497. -" (default: %s)\n"
  498. -" -v 1|5|9|10 NetFlow export packet version\n"
  499. -" -L hoplimit Set TTL/hoplimit for export datagrams\n"
  500. -" -T full|proto|ip Set flow tracking level (default: full)\n"
  501. -" -6 Track IPv6 flows, regardless of whether selected \n"
  502. -" NetFlow export protocol supports it\n"
  503. -" -d Don't daemonise (run in foreground)\n"
  504. -" -D Debug mode: foreground + verbosity + track v6 flows\n"
  505. -" -s sampling_rate Specify periodical sampling rate (denominator)\n"
  506. -" -h Display this help\n"
  507. +" -i [idx:]interface Specify interface to listen on\n"
  508. +" -r pcap_file Specify packet capture file to read\n"
  509. +" -t timeout=time Specify named timeout\n"
  510. +" -m max_flows Specify maximum number of flows to track (default %d)\n"
  511. +" -n host:port Send Cisco NetFlow(tm)-compatible packets to host:port\n"
  512. +" -p pidfile Record pid in specified file\n"
  513. +" (default: %s)\n"
  514. +" -c pidfile Location of control socket\n"
  515. +" (default: %s)\n"
  516. +" -v 1|5|9|10 NetFlow export packet version\n"
  517. +" (10 means IPFI)\n"
  518. +" -L hoplimit Set TTL/hoplimit for export datagrams\n"
  519. +" -T full|port|proto|ip Set flow tracking level (default: full)\n"
  520. +" -6 Track IPv6 flows, regardless of whether selected \n"
  521. +" NetFlow export protocol supports it\n"
  522. +" -d Don't daemonise (run in foreground)\n"
  523. +" -D Debug mode: foreground + verbosity + track v6 flows\n"
  524. +" -s sampling_rate Specify periodical sampling rate (denominator)\n"
  525. +" -P udp|tcp|sctp Specify transport layer protocol for exporting packets\n"
  526. +" -A sec|milli|micro|nano Specify absolute time format form exporting records\n"
  527. +" -s sampling_rate Specify periodical sampling rate (denominator)\n"
  528. +" -h Display this help\n"
  529. "\n"
  530. "Valid timeout names and default values:\n"
  531. " tcp (default %6d)"
  532. @@ -1695,6 +1699,7 @@
  533. struct NETFLOW_TARGET target;
  534. struct CB_CTXT cb_ctxt;
  535. struct pollfd pl[2];
  536. + int protocol = IPPROTO_UDP;
  537. closefrom(STDERR_FILENO + 1);
  538. @@ -1714,7 +1719,7 @@
  539. dontfork_flag = 0;
  540. always_v6 = 0;
  541. - while ((ch = getopt(argc, argv, "6hdDL:T:i:r:f:t:n:m:p:c:v:s:")) != -1) {
  542. + while ((ch = getopt(argc, argv, "6hdDL:T:i:r:f:t:n:m:p:c:v:s:P:A:")) != -1) {
  543. switch (ch) {
  544. case '6':
  545. always_v6 = 1;
  546. @@ -1766,6 +1771,8 @@
  547. case 'T':
  548. if (strcasecmp(optarg, "full") == 0)
  549. flowtrack.param.track_level = TRACK_FULL;
  550. + else if (strcasecmp(optarg, "port") == 0)
  551. + flowtrack.param.track_level = TRACK_IP_PROTO_PORT;
  552. else if (strcasecmp(optarg, "proto") == 0)
  553. flowtrack.param.track_level = TRACK_IP_PROTO;
  554. else if (strcasecmp(optarg, "ip") == 0)
  555. @@ -1824,6 +1831,38 @@
  556. flowtrack.param.option.sample = 0;
  557. }
  558. break;
  559. + case 'P':
  560. + if (strcasecmp(optarg, "udp") == 0)
  561. + protocol = IPPROTO_UDP;
  562. + else if (strcasecmp(optarg, "tcp") == 0)
  563. + protocol = IPPROTO_TCP;
  564. +#ifdef IPPROTO_SCTP
  565. + else if (strcasecmp(optarg, "sctp") == 0)
  566. + protocol = IPPROTO_SCTP;
  567. +#endif
  568. + else {
  569. + fprintf(stderr, "Unknown transport layer protocol"
  570. + "\n");
  571. + usage();
  572. + exit(1);
  573. + }
  574. + break;
  575. + case 'A':
  576. + if (strcasecmp(optarg, "sec") == 0)
  577. + flowtrack.param.time_format = 's';
  578. + else if (strcasecmp(optarg, "milli") == 0)
  579. + flowtrack.param.time_format = 'm';
  580. + else if (strcasecmp(optarg, "micro") == 0)
  581. + flowtrack.param.time_format = 'M';
  582. + else if (strcasecmp(optarg, "nano") == 0)
  583. + flowtrack.param.time_format = 'n';
  584. + else {
  585. + fprintf(stderr, "Unknown time format"
  586. + "\n");
  587. + usage();
  588. + exit(1);
  589. + }
  590. + break;
  591. default:
  592. fprintf(stderr, "Invalid commandline option.\n");
  593. usage();
  594. @@ -1852,7 +1891,7 @@
  595. fprintf(stderr, "getnameinfo: %d\n", err);
  596. exit(1);
  597. }
  598. - target.fd = connsock(&dest, dest_len, hoplimit);
  599. + target.fd = connsock(&dest, dest_len, hoplimit, protocol);
  600. }
  601. /* Control socket */
  602. --- a/softflowd.h
  603. +++ b/softflowd.h
  604. @@ -69,9 +69,10 @@
  605. };
  606. /* Flow tracking levels */
  607. -#define TRACK_FULL 1 /* src/dst/addr/port/proto 5-tuple */
  608. -#define TRACK_IP_PROTO 2 /* src/dst/proto 3-tuple */
  609. -#define TRACK_IP_ONLY 3 /* src/dst tuple */
  610. +#define TRACK_FULL 1 /* src/dst/addr/port/proto/tos 6-tuple */
  611. +#define TRACK_IP_PROTO_PORT 2 /* src/dst/addr/port/proto 5-tuple */
  612. +#define TRACK_IP_PROTO 3 /* src/dst/proto 3-tuple */
  613. +#define TRACK_IP_ONLY 4 /* src/dst tuple */
  614. /*
  615. * This structure contains optional information carried by Option Data
  616. @@ -136,6 +137,7 @@
  617. /* Optional information */
  618. struct OPTION option;
  619. + char time_format;
  620. };
  621. /*
  622. * This structure is the root of the flow tracking system.
  623. @@ -166,6 +168,15 @@
  624. struct EXPIRY *expiry; /* Pointer to expiry record */
  625. FLOW_ENTRY(FLOW) trp; /* Tree pointer */
  626. + /* Per-flow statistics (all in _host_ byte order) */
  627. + u_int64_t flow_seq; /* Flow ID */
  628. + struct timeval flow_start; /* Time of creation */
  629. + struct timeval flow_last; /* Time of last traffic */
  630. +
  631. + /* Per-endpoint statistics (all in _host_ byte order) */
  632. + u_int32_t octets[2]; /* Octets so far */
  633. + u_int32_t packets[2]; /* Packets so far */
  634. +
  635. /* Flow identity (all are in network byte order) */
  636. int af; /* Address family of flow */
  637. u_int32_t ip6_flowlabel[2]; /* IPv6 Flowlabel */
  638. @@ -175,16 +186,8 @@
  639. } addr[2]; /* Endpoint addresses */
  640. u_int16_t port[2]; /* Endpoint ports */
  641. u_int8_t tcp_flags[2]; /* Cumulative OR of flags */
  642. + u_int8_t tos[2]; /* Tos */
  643. u_int8_t protocol; /* Protocol */
  644. -
  645. - /* Per-flow statistics (all in _host_ byte order) */
  646. - u_int64_t flow_seq; /* Flow ID */
  647. - struct timeval flow_start; /* Time of creation */
  648. - struct timeval flow_last; /* Time of last traffic */
  649. -
  650. - /* Per-endpoint statistics (all in _host_ byte order) */
  651. - u_int32_t octets[2]; /* Octets so far */
  652. - u_int32_t packets[2]; /* Packets so far */
  653. };
  654. /*