ipfix.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. /*
  2. * Copyright 2002 Damien Miller <djm@mindrot.org> All rights reserved.
  3. * Copyright 2012 Hitoshi Irino <irino@sfc.wide.ad.jp> All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "common.h"
  26. #include "log.h"
  27. #include "treetype.h"
  28. #include "softflowd.h"
  29. #include "netflow9.h"
  30. #include "ipfix.h"
  31. #include "psamp.h"
  32. const struct IPFIX_FIELD_SPECIFIER field_v4[] = {
  33. {IPFIX_sourceIPv4Address, 4},
  34. {IPFIX_destinationIPv4Address, 4}
  35. };
  36. const struct IPFIX_FIELD_SPECIFIER field_v6[] = {
  37. {IPFIX_sourceIPv6Address, 16},
  38. {IPFIX_destinationIPv6Address, 16}
  39. };
  40. const struct IPFIX_FIELD_SPECIFIER field_common[] = {
  41. {IPFIX_octetDeltaCount, 4},
  42. {IPFIX_packetDeltaCount, 4},
  43. {IPFIX_ingressInterface, 4},
  44. {IPFIX_egressInterface, 4},
  45. {IPFIX_flowDirection, 1},
  46. {IPFIX_flowEndReason, 1},
  47. #ifdef ENABLE_IFNAME
  48. {IPFIX_interfaceName, IFNAMSIZ}
  49. #endif
  50. };
  51. const struct IPFIX_FIELD_SPECIFIER field_transport[] = {
  52. {IPFIX_sourceTransportPort, 2},
  53. {IPFIX_destinationTransportPort, 2},
  54. {IPFIX_protocolIdentifier, 1},
  55. {IPFIX_tcpControlBits, 1},
  56. {IPFIX_ipVersion, 1},
  57. {IPFIX_ipClassOfService, 1}
  58. };
  59. const struct IPFIX_FIELD_SPECIFIER field_icmp4[] = {
  60. {IPFIX_icmpTypeCodeIPv4, 2},
  61. {IPFIX_protocolIdentifier, 1},
  62. {IPFIX_ipVersion, 1},
  63. {IPFIX_ipClassOfService, 1}
  64. };
  65. const struct IPFIX_FIELD_SPECIFIER field_icmp6[] = {
  66. {IPFIX_icmpTypeCodeIPv6, 2},
  67. {IPFIX_protocolIdentifier, 1},
  68. {IPFIX_ipVersion, 1},
  69. {IPFIX_ipClassOfService, 1}
  70. };
  71. const struct IPFIX_FIELD_SPECIFIER field_vlan[] = {
  72. {IPFIX_vlanId, 2},
  73. {IPFIX_postVlanId, 2}
  74. };
  75. const struct IPFIX_FIELD_SPECIFIER field_ether[] = {
  76. {IPFIX_sourceMacAddress, 6},
  77. {IPFIX_postDestinationMacAddress, 6}
  78. };
  79. const struct IPFIX_FIELD_SPECIFIER field_timesec[] = {
  80. {IPFIX_flowStartSeconds, 4},
  81. {IPFIX_flowEndSeconds, 4}
  82. };
  83. const struct IPFIX_FIELD_SPECIFIER field_timemsec[] = {
  84. {IPFIX_flowStartMilliSeconds, 8},
  85. {IPFIX_flowEndMilliSeconds, 8}
  86. };
  87. const struct IPFIX_FIELD_SPECIFIER field_timeusec[] = {
  88. {IPFIX_flowStartMicroSeconds, 8},
  89. {IPFIX_flowEndMicroSeconds, 8}
  90. };
  91. const struct IPFIX_FIELD_SPECIFIER field_timensec[] = {
  92. {IPFIX_flowStartNanoSeconds, 8},
  93. {IPFIX_flowEndNanoSeconds, 8}
  94. };
  95. const struct IPFIX_FIELD_SPECIFIER field_timesysup[] = {
  96. {IPFIX_flowStartSysUpTime, 4},
  97. {IPFIX_flowEndSysUpTime, 4}
  98. };
  99. const struct IPFIX_FIELD_SPECIFIER field_bicommon[] = {
  100. {IPFIX_octetDeltaCount, 4},
  101. {IPFIX_packetDeltaCount, 4},
  102. {IPFIX_ipClassOfService, 1}
  103. };
  104. const struct IPFIX_FIELD_SPECIFIER field_bitransport[] =
  105. { {IPFIX_tcpControlBits, 1} };
  106. const struct IPFIX_FIELD_SPECIFIER field_biicmp4[] =
  107. { {IPFIX_icmpTypeCodeIPv4, 2} };
  108. const struct IPFIX_FIELD_SPECIFIER field_biicmp6[] =
  109. { {IPFIX_icmpTypeCodeIPv6, 2} };
  110. const struct IPFIX_FIELD_SPECIFIER field_scope[] =
  111. { {IPFIX_meteringProcessId, 4} };
  112. const struct IPFIX_FIELD_SPECIFIER field_option[] = {
  113. {IPFIX_systemInitTimeMilliseconds, 8},
  114. {PSAMP_samplingPacketInterval, 4},
  115. {PSAMP_samplingPacketSpace, 4},
  116. {PSAMP_selectorAlgorithm, 2},
  117. {IPFIX_interfaceName, IFNAMSIZ}
  118. };
  119. const struct IPFIX_FIELD_SPECIFIER field_nf9scope[] =
  120. { {NFLOW9_OPTION_SCOPE_INTERFACE, 4} };
  121. const struct IPFIX_FIELD_SPECIFIER field_nf9option[] = {
  122. {NFLOW9_SAMPLING_INTERVAL, 4},
  123. {NFLOW9_SAMPLING_ALGORITHM, 1},
  124. {IPFIX_interfaceName, IFNAMSIZ}
  125. };
  126. /* Stuff pertaining to the templates that softflowd uses */
  127. #define IPFIX_SOFTFLOWD_TEMPLATE_IPRECORDS \
  128. sizeof(field_v4) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  129. #define IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS \
  130. sizeof(field_timesysup) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  131. #define IPFIX_SOFTFLOWD_TEMPLATE_COMMONRECORDS \
  132. sizeof(field_common) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  133. #define IPFIX_SOFTFLOWD_TEMPLATE_TRANSPORTRECORDS \
  134. sizeof(field_transport) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  135. #define IPFIX_SOFTFLOWD_TEMPLATE_ICMPRECORDS \
  136. sizeof(field_icmp4) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  137. #define IPFIX_SOFTFLOWD_TEMPLATE_VLANRECORDS \
  138. sizeof(field_vlan) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  139. #define IPFIX_SOFTFLOWD_TEMPLATE_ETHERRECORDS \
  140. sizeof(field_ether) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  141. #define IPFIX_SOFTFLOWD_TEMPLATE_BICOMMONRECORDS \
  142. sizeof(field_bicommon) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  143. #define IPFIX_SOFTFLOWD_TEMPLATE_BITRANSPORTRECORDS \
  144. sizeof(field_bitransport) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  145. #define IPFIX_SOFTFLOWD_TEMPLATE_BIICMPRECORDS \
  146. sizeof(field_biicmp4) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  147. #define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS \
  148. IPFIX_SOFTFLOWD_TEMPLATE_IPRECORDS + \
  149. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS + \
  150. IPFIX_SOFTFLOWD_TEMPLATE_COMMONRECORDS + \
  151. IPFIX_SOFTFLOWD_TEMPLATE_TRANSPORTRECORDS + \
  152. IPFIX_SOFTFLOWD_TEMPLATE_VLANRECORDS + \
  153. IPFIX_SOFTFLOWD_TEMPLATE_ETHERRECORDS
  154. #define IPFIX_SOFTFLOWD_TEMPLATE_BI_NRECORDS \
  155. IPFIX_SOFTFLOWD_TEMPLATE_BICOMMONRECORDS + \
  156. IPFIX_SOFTFLOWD_TEMPLATE_BITRANSPORTRECORDS
  157. struct IPFIX_SOFTFLOWD_TEMPLATE {
  158. struct IPFIX_TEMPLATE_SET_HEADER h;
  159. struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS];
  160. struct IPFIX_VENDOR_FIELD_SPECIFIER
  161. v[IPFIX_SOFTFLOWD_TEMPLATE_BI_NRECORDS];
  162. u_int16_t data_len, bi_count;
  163. } __packed;
  164. #define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS \
  165. sizeof(field_scope) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  166. #define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS \
  167. sizeof(field_option) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  168. #define NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS \
  169. sizeof(field_nf9scope) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  170. #define NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS \
  171. sizeof(field_nf9option) / sizeof(struct IPFIX_FIELD_SPECIFIER)
  172. struct IPFIX_SOFTFLOWD_OPTION_TEMPLATE {
  173. struct IPFIX_OPTION_TEMPLATE_SET_HEADER h;
  174. struct IPFIX_FIELD_SPECIFIER
  175. s[IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS];
  176. struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS];
  177. } __packed;
  178. /* softflowd data set */
  179. struct IPFIX_SOFTFLOWD_DATA_COMMON {
  180. u_int32_t octetDeltaCount, packetDeltaCount;
  181. u_int32_t ingressInterface, egressInterface;
  182. u_int8_t flowDirection, flowEndReason;
  183. #ifdef ENABLE_IFNAME
  184. char interfaceName[IFNAMSIZ];
  185. #endif
  186. } __packed;
  187. struct IPFIX_SOFTFLOWD_DATA_TRANSPORT {
  188. u_int16_t sourceTransportPort, destinationTransportPort;
  189. u_int8_t protocolIdentifier, tcpControlBits, ipVersion, ipClassOfService;
  190. } __packed;
  191. struct IPFIX_SOFTFLOWD_DATA_ICMP {
  192. u_int16_t icmpTypeCode;
  193. u_int8_t protocolIdentifier, ipVersion, ipClassOfService;
  194. } __packed;
  195. struct IPFIX_SOFTFLOWD_DATA_VLAN {
  196. u_int16_t vlanId, postVlanId;
  197. } __packed;
  198. struct IPFIX_SOFTFLOWD_DATA_ETHER {
  199. u_int8_t sourceMacAddress[6], destinationMacAddress[6];
  200. } __packed;
  201. struct IPFIX_SOFTFLOWD_DATA_BICOMMON {
  202. u_int32_t octetDeltaCount, packetDeltaCount;
  203. u_int8_t ipClassOfService;
  204. } __packed;
  205. struct IPFIX_SOFTFLOWD_DATA_BITRANSPORT {
  206. u_int8_t tcpControlBits;
  207. } __packed;
  208. struct IPFIX_SOFTFLOWD_DATA_BIICMP {
  209. u_int16_t icmpTypeCode;
  210. } __packed;
  211. union IPFIX_SOFTFLOWD_DATA_TIME {
  212. struct {
  213. u_int32_t start;
  214. u_int32_t end;
  215. } u32;
  216. struct {
  217. u_int64_t start;
  218. u_int64_t end;
  219. } u64;
  220. };
  221. struct IPFIX_SOFTFLOWD_DATA_V4ADDR {
  222. u_int32_t sourceIPv4Address, destinationIPv4Address;
  223. } __packed;
  224. struct IPFIX_SOFTFLOWD_DATA_V6ADDR {
  225. struct in6_addr sourceIPv6Address, destinationIPv6Address;
  226. } __packed;
  227. struct IPFIX_SOFTFLOWD_OPTION_DATA {
  228. struct IPFIX_SET_HEADER c;
  229. u_int32_t scope_pid;
  230. u_int64_t systemInitTimeMilliseconds;
  231. u_int32_t samplingInterval;
  232. u_int32_t samplingSpace;
  233. u_int16_t samplingAlgorithm;
  234. char interfaceName[IFNAMSIZ];
  235. } __packed;
  236. struct NFLOW9_SOFTFLOWD_OPTION_DATA {
  237. struct IPFIX_SET_HEADER c;
  238. u_int32_t scope_ifidx;
  239. u_int32_t samplingInterval;
  240. u_int8_t samplingAlgorithm;
  241. char interfaceName[IFNAMSIZ];
  242. } __packed;
  243. /* Local data: templates and counters */
  244. #define IPFIX_SOFTFLOWD_MAX_PACKET_SIZE 1428
  245. #define IPFIX_SOFTFLOWD_V4_TEMPLATE_ID 1024
  246. #define IPFIX_SOFTFLOWD_ICMPV4_TEMPLATE_ID 1025
  247. #define IPFIX_SOFTFLOWD_V6_TEMPLATE_ID 2048
  248. #define IPFIX_SOFTFLOWD_ICMPV6_TEMPLATE_ID 2049
  249. #define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID 256
  250. #define IPFIX_DEFAULT_TEMPLATE_INTERVAL 16
  251. /* ... */
  252. #define IPFIX_OPTION_SCOPE_SYSTEM 1
  253. #define IPFIX_OPTION_SCOPE_INTERFACE 2
  254. #define IPFIX_OPTION_SCOPE_LINECARD 3
  255. #define IPFIX_OPTION_SCOPE_CACHE 4
  256. #define IPFIX_OPTION_SCOPE_TEMPLATE 5
  257. /* ... */
  258. #define IPFIX_SAMPLING_ALGORITHM_DETERMINISTIC 1
  259. #define IPFIX_SAMPLING_ALGORITHM_RANDOM 2
  260. /* ... */
  261. // prototype
  262. void memcpy_template (u_char * packet, u_int * offset,
  263. struct IPFIX_SOFTFLOWD_TEMPLATE *template,
  264. u_int8_t bi_flag, u_int8_t max_num_label);
  265. // variables
  266. enum { TMPLV4, TMPLICMPV4, TMPLV6, TMPLICMPV6, TMPLMAX };
  267. static struct IPFIX_SOFTFLOWD_TEMPLATE templates[TMPLMAX];
  268. static struct IPFIX_SOFTFLOWD_OPTION_TEMPLATE option_template;
  269. static struct IPFIX_SOFTFLOWD_OPTION_DATA option_data;
  270. static struct NFLOW9_SOFTFLOWD_OPTION_DATA nf9opt_data;
  271. static int ipfix_pkts_until_template = -1;
  272. int
  273. ipfix_init_fields (struct IPFIX_FIELD_SPECIFIER *dst,
  274. u_int * index,
  275. const struct IPFIX_FIELD_SPECIFIER *src,
  276. u_int field_number) {
  277. int i, length = 0;
  278. for (i = 0; i < field_number; i++) {
  279. dst[*index + i].ie = htons (src[i].ie);
  280. dst[*index + i].length = htons (src[i].length);
  281. length += src[i].length;
  282. }
  283. *index += field_number;
  284. return length;
  285. }
  286. void
  287. conv_unix_to_ntp (struct timeval tv, struct ntp_time_t *ntp) {
  288. if (ntp != NULL) {
  289. ntp->second = tv.tv_sec + 0x83AA7E80;
  290. ntp->fraction =
  291. (uint32_t) ((double) (tv.tv_usec + 1) * (double) (1LL << 32) * 1.0e-6);
  292. }
  293. }
  294. struct timeval
  295. conv_ntp_to_unix (struct ntp_time_t ntp) {
  296. struct timeval tv = {
  297. ntp.second - 0x83AA7E80, // the seconds from Jan 1, 1900 to Jan 1, 1970
  298. (uint32_t) ((double) ntp.fraction * 1.0e6 / (double) (1LL << 32))
  299. };
  300. return tv;
  301. }
  302. static int
  303. ipfix_init_bifields (struct IPFIX_SOFTFLOWD_TEMPLATE *template,
  304. u_int * index,
  305. const struct IPFIX_FIELD_SPECIFIER *fields,
  306. u_int field_number) {
  307. int i, length = 0;
  308. for (i = 0; i < field_number; i++) {
  309. template->v[*index + i].ie = htons (fields[i].ie | 0x8000);
  310. template->v[*index + i].length = htons (fields[i].length);
  311. template->v[*index + i].pen = htonl (REVERSE_PEN);
  312. length += fields[i].length;
  313. }
  314. *index += field_number;
  315. return length;
  316. }
  317. static int
  318. ipfix_init_template_time (struct FLOWTRACKPARAMETERS *param,
  319. struct IPFIX_SOFTFLOWD_TEMPLATE *template,
  320. u_int * index) {
  321. int length = 0;
  322. if (param->time_format == 's') {
  323. length = ipfix_init_fields (template->r, index,
  324. field_timesec,
  325. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS);
  326. } else if (param->time_format == 'm') {
  327. length = ipfix_init_fields (template->r, index,
  328. field_timemsec,
  329. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS);
  330. } else if (param->time_format == 'M') {
  331. length = ipfix_init_fields (template->r, index,
  332. field_timeusec,
  333. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS);
  334. } else if (param->time_format == 'n') {
  335. length = ipfix_init_fields (template->r, index,
  336. field_timensec,
  337. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS);
  338. } else {
  339. length = ipfix_init_fields (template->r, index,
  340. field_timesysup,
  341. IPFIX_SOFTFLOWD_TEMPLATE_TIMERECORDS);
  342. }
  343. return length;
  344. }
  345. static void
  346. ipfix_init_template_unity (struct FLOWTRACKPARAMETERS *param,
  347. struct IPFIX_SOFTFLOWD_TEMPLATE *template,
  348. u_int template_id, u_int8_t v6_flag,
  349. u_int8_t icmp_flag, u_int8_t bi_flag,
  350. u_int16_t version) {
  351. u_int index = 0, bi_index = 0, length = 0;
  352. memset (template, 0, sizeof (*template));
  353. template->h.c.set_id = htons (version == 10 ?
  354. IPFIX_TEMPLATE_SET_ID :
  355. NFLOW9_TEMPLATE_SET_ID);
  356. template->h.r.template_id = htons (template_id);
  357. if (v6_flag) {
  358. length += ipfix_init_fields (template->r, &index,
  359. field_v6,
  360. IPFIX_SOFTFLOWD_TEMPLATE_IPRECORDS);
  361. } else {
  362. length += ipfix_init_fields (template->r, &index,
  363. field_v4,
  364. IPFIX_SOFTFLOWD_TEMPLATE_IPRECORDS);
  365. }
  366. length += ipfix_init_template_time (param, template, &index);
  367. length += ipfix_init_fields (template->r, &index,
  368. field_common,
  369. IPFIX_SOFTFLOWD_TEMPLATE_COMMONRECORDS);
  370. if (icmp_flag) {
  371. if (v6_flag) {
  372. length += ipfix_init_fields (template->r, &index,
  373. field_icmp6,
  374. IPFIX_SOFTFLOWD_TEMPLATE_ICMPRECORDS);
  375. } else {
  376. length += ipfix_init_fields (template->r, &index,
  377. field_icmp4,
  378. IPFIX_SOFTFLOWD_TEMPLATE_ICMPRECORDS);
  379. }
  380. } else {
  381. length += ipfix_init_fields (template->r, &index,
  382. field_transport,
  383. IPFIX_SOFTFLOWD_TEMPLATE_TRANSPORTRECORDS);
  384. }
  385. if (param->track_level >= TRACK_FULL_VLAN) {
  386. length += ipfix_init_fields (template->r, &index,
  387. field_vlan,
  388. IPFIX_SOFTFLOWD_TEMPLATE_VLANRECORDS);
  389. }
  390. if (param->track_level >= TRACK_FULL_VLAN_ETHER) {
  391. length += ipfix_init_fields (template->r, &index,
  392. field_ether,
  393. IPFIX_SOFTFLOWD_TEMPLATE_ETHERRECORDS);
  394. }
  395. if (bi_flag) {
  396. length +=
  397. ipfix_init_bifields (template, &bi_index,
  398. field_bicommon,
  399. IPFIX_SOFTFLOWD_TEMPLATE_BICOMMONRECORDS);
  400. if (icmp_flag) {
  401. if (v6_flag) {
  402. length +=
  403. ipfix_init_bifields (template, &bi_index,
  404. field_biicmp6,
  405. IPFIX_SOFTFLOWD_TEMPLATE_BIICMPRECORDS);
  406. } else {
  407. length +=
  408. ipfix_init_bifields (template, &bi_index,
  409. field_biicmp4,
  410. IPFIX_SOFTFLOWD_TEMPLATE_BIICMPRECORDS);
  411. }
  412. } else {
  413. length +=
  414. ipfix_init_bifields (template, &bi_index,
  415. field_bitransport,
  416. IPFIX_SOFTFLOWD_TEMPLATE_BITRANSPORTRECORDS);
  417. }
  418. }
  419. template->bi_count = bi_index;
  420. template->h.r.count = htons (index + bi_index + param->max_num_label); // mpls
  421. template->h.c.length =
  422. htons (sizeof (struct IPFIX_TEMPLATE_SET_HEADER) +
  423. index * sizeof (struct IPFIX_FIELD_SPECIFIER) +
  424. bi_index * sizeof (struct IPFIX_VENDOR_FIELD_SPECIFIER) +
  425. param->max_num_label * sizeof (struct IPFIX_FIELD_SPECIFIER));
  426. template->data_len =
  427. length + param->max_num_label * IPFIX_mplsLabelStackSection_SIZE;
  428. }
  429. static void
  430. ipfix_init_template (struct FLOWTRACKPARAMETERS *param,
  431. u_int8_t bi_flag, u_int16_t version) {
  432. u_int8_t v6_flag = 0, icmp_flag = 0;
  433. u_int16_t template_id = 0;
  434. int i = 0;
  435. for (i = 0; i < TMPLMAX; i++) {
  436. switch (i) {
  437. case TMPLV4:
  438. v6_flag = 0;
  439. icmp_flag = 0;
  440. template_id = IPFIX_SOFTFLOWD_V4_TEMPLATE_ID;
  441. break;
  442. case TMPLICMPV4:
  443. v6_flag = 0;
  444. icmp_flag = 1;
  445. template_id = IPFIX_SOFTFLOWD_ICMPV4_TEMPLATE_ID;
  446. break;
  447. case TMPLV6:
  448. v6_flag = 1;
  449. icmp_flag = 0;
  450. template_id = IPFIX_SOFTFLOWD_V6_TEMPLATE_ID;
  451. break;
  452. case TMPLICMPV6:
  453. v6_flag = 1;
  454. icmp_flag = 1;
  455. template_id = IPFIX_SOFTFLOWD_ICMPV6_TEMPLATE_ID;
  456. break;
  457. }
  458. ipfix_init_template_unity (param, &templates[i],
  459. template_id, v6_flag,
  460. icmp_flag, bi_flag, version);
  461. }
  462. }
  463. static void
  464. nflow9_init_option (u_int16_t ifidx, struct OPTION *option) {
  465. u_int scope_index = 0, option_index = 0;
  466. u_int16_t scope_len =
  467. NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS *
  468. sizeof (struct IPFIX_FIELD_SPECIFIER);
  469. u_int16_t opt_len =
  470. NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS *
  471. sizeof (struct IPFIX_FIELD_SPECIFIER);
  472. memset (&option_template, 0, sizeof (option_template));
  473. option_template.h.c.set_id = htons (NFLOW9_OPTION_TEMPLATE_SET_ID);
  474. option_template.h.c.length =
  475. htons (sizeof (option_template.h) + scope_len + opt_len);
  476. option_template.h.u.n.template_id =
  477. htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
  478. option_template.h.u.n.scope_length = htons (scope_len);
  479. option_template.h.u.n.option_length = htons (opt_len);
  480. ipfix_init_fields (option_template.s, &scope_index,
  481. field_nf9scope,
  482. NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS);
  483. ipfix_init_fields (option_template.r, &option_index,
  484. field_nf9option,
  485. NFLOW9_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS);
  486. memset (&nf9opt_data, 0, sizeof (nf9opt_data));
  487. nf9opt_data.c.set_id = htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
  488. nf9opt_data.c.length = htons (sizeof (nf9opt_data));
  489. nf9opt_data.scope_ifidx = htonl (ifidx);
  490. nf9opt_data.samplingInterval =
  491. htonl (option->sample > 1 ? option->sample : 1);
  492. nf9opt_data.samplingAlgorithm = NFLOW9_SAMPLING_ALGORITHM_DETERMINISTIC;
  493. strncpy (nf9opt_data.interfaceName, option->interfaceName,
  494. strlen (option->interfaceName) <
  495. sizeof (nf9opt_data.interfaceName) ?
  496. strlen (option->interfaceName) :
  497. sizeof (nf9opt_data.interfaceName));
  498. }
  499. static void
  500. ipfix_init_option (struct timeval *system_boot_time, struct OPTION *option) {
  501. u_int scope_index = 0, option_index = 0;
  502. memset (&option_template, 0, sizeof (option_template));
  503. option_template.h.c.set_id = htons (IPFIX_OPTION_TEMPLATE_SET_ID);
  504. option_template.h.c.length = htons (sizeof (option_template));
  505. option_template.h.u.i.r.template_id =
  506. htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
  507. option_template.h.u.i.r.count =
  508. htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS +
  509. IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS);
  510. option_template.h.u.i.scope_count =
  511. htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS);
  512. ipfix_init_fields (option_template.s, &scope_index,
  513. field_scope,
  514. IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS);
  515. ipfix_init_fields (option_template.r, &option_index, field_option,
  516. IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS);
  517. memset (&option_data, 0, sizeof (option_data));
  518. option_data.c.set_id = htons (IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
  519. option_data.c.length = htons (sizeof (option_data));
  520. option_data.scope_pid = htonl ((u_int32_t) option->meteringProcessId);
  521. #if defined(htobe64) || defined(HAVE_DECL_HTOBE64)
  522. option_data.systemInitTimeMilliseconds =
  523. htobe64 ((u_int64_t) system_boot_time->tv_sec * 1000 +
  524. (u_int64_t) system_boot_time->tv_usec / 1000);
  525. #endif
  526. option_data.samplingAlgorithm = htons (PSAMP_selectorAlgorithm_count);
  527. option_data.samplingInterval = htonl (1);
  528. option_data.samplingSpace =
  529. htonl (option->sample > 0 ? option->sample - 1 : 0);
  530. strncpy (option_data.interfaceName, option->interfaceName,
  531. strlen (option->interfaceName) <
  532. sizeof (option_data.interfaceName) ?
  533. strlen (option->interfaceName) :
  534. sizeof (option_data.interfaceName));
  535. }
  536. static int
  537. copy_data_time (union IPFIX_SOFTFLOWD_DATA_TIME *dt,
  538. const struct FLOW *flow,
  539. const struct timeval *system_boot_time,
  540. struct FLOWTRACKPARAMETERS *param) {
  541. int length = (param->time_format == 'm' || param->time_format == 'M'
  542. || param->time_format == 'n') ? 16 : 8;
  543. if (dt == NULL)
  544. return -1;
  545. switch (param->time_format) {
  546. struct ntp_time_t ntptime;
  547. case 's':
  548. dt->u32.start = htonl (flow->flow_start.tv_sec);
  549. dt->u32.end = htonl (flow->flow_last.tv_sec);
  550. break;
  551. #if defined(htobe64) || defined(HAVE_DECL_HTOBE64)
  552. case 'm':
  553. dt->u64.start =
  554. htobe64 ((u_int64_t) flow->flow_start.tv_sec * 1000 +
  555. (u_int64_t) flow->flow_start.tv_usec / 1000);
  556. dt->u64.end =
  557. htobe64 ((u_int64_t) flow->flow_last.tv_sec * 1000 +
  558. (u_int64_t) flow->flow_last.tv_usec / 1000);
  559. break;
  560. case 'M':
  561. case 'n':
  562. conv_unix_to_ntp ((struct timeval) flow->flow_start, &ntptime);
  563. dt->u64.start =
  564. htobe64 ((u_int64_t) ntptime.second << 32 | ntptime.fraction);
  565. conv_unix_to_ntp ((struct timeval) flow->flow_last, &ntptime);
  566. dt->u64.end =
  567. htobe64 ((u_int64_t) ntptime.second << 32 | ntptime.fraction);
  568. break;
  569. #endif
  570. default:
  571. dt->u32.start =
  572. htonl (timeval_sub_ms (&flow->flow_start, system_boot_time));
  573. dt->u32.end = htonl (timeval_sub_ms (&flow->flow_last, system_boot_time));
  574. break;
  575. }
  576. return length;
  577. }
  578. static u_int
  579. ipfix_flow_to_template_index (const struct FLOW *flow) {
  580. u_int index = 0;
  581. if (flow->af == AF_INET) {
  582. index = (flow->protocol == IPPROTO_ICMP) ? TMPLICMPV4 : TMPLV4;
  583. } else if (flow->af == AF_INET6) {
  584. index = (flow->protocol == IPPROTO_ICMPV6) ? TMPLICMPV6 : TMPLV6;
  585. }
  586. return index;
  587. }
  588. static int
  589. ipfix_flow_to_flowset (const struct FLOW *flow, u_char * packet,
  590. u_int len, u_int16_t ifidx,
  591. const struct timeval *system_boot_time,
  592. u_int * len_used,
  593. struct FLOWTRACKPARAMETERS *param, u_int8_t bi_flag) {
  594. struct IPFIX_SOFTFLOWD_DATA_V4ADDR *d4[2] = { NULL, NULL };
  595. struct IPFIX_SOFTFLOWD_DATA_V6ADDR *d6[2] = { NULL, NULL };
  596. union IPFIX_SOFTFLOWD_DATA_TIME *dt[2] = { NULL, NULL };
  597. struct IPFIX_SOFTFLOWD_DATA_COMMON *dc[2] = { NULL, NULL };
  598. struct IPFIX_SOFTFLOWD_DATA_TRANSPORT *dtr[2] = { NULL, NULL };
  599. struct IPFIX_SOFTFLOWD_DATA_ICMP *di[2] = { NULL, NULL };
  600. struct IPFIX_SOFTFLOWD_DATA_VLAN *dv[2] = { NULL, NULL };
  601. struct IPFIX_SOFTFLOWD_DATA_ETHER *de[2] = { NULL, NULL };
  602. struct IPFIX_SOFTFLOWD_DATA_BICOMMON *dbc = NULL;
  603. struct IPFIX_SOFTFLOWD_DATA_BITRANSPORT *dbtr = NULL;
  604. struct IPFIX_SOFTFLOWD_DATA_BIICMP *dbi = NULL;
  605. struct OPTION *option = &param->option;
  606. u_int freclen = 0, nflows = 0, offset = 0;
  607. u_int frecnum = bi_flag ? 1 : 2;
  608. u_int tmplindex = ipfix_flow_to_template_index (flow);
  609. int i = 0, k = 0;
  610. freclen = templates[tmplindex].data_len;
  611. if (len < freclen * frecnum)
  612. return (-1);
  613. for (i = 0; i < frecnum; i++) {
  614. if (bi_flag == 0 && flow->octets[i] == 0)
  615. continue;
  616. nflows++;
  617. if (flow->af == AF_INET) {
  618. d4[i] = (struct IPFIX_SOFTFLOWD_DATA_V4ADDR *) &packet[offset];
  619. memcpy (&d4[i]->sourceIPv4Address, &flow->addr[i].v4, 4);
  620. memcpy (&d4[i]->destinationIPv4Address, &flow->addr[i ^ 1].v4, 4);
  621. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_V4ADDR);
  622. } else if (flow->af == AF_INET6) {
  623. d6[i] = (struct IPFIX_SOFTFLOWD_DATA_V6ADDR *) &packet[offset];
  624. memcpy (&d6[i]->sourceIPv6Address, &flow->addr[i].v6, 16);
  625. memcpy (&d6[i]->destinationIPv6Address, &flow->addr[i ^ 1].v6, 16);
  626. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_V6ADDR);
  627. }
  628. dt[i] = (union IPFIX_SOFTFLOWD_DATA_TIME *) &packet[offset];
  629. offset += copy_data_time (dt[i], flow, system_boot_time, param);
  630. dc[i] = (struct IPFIX_SOFTFLOWD_DATA_COMMON *) &packet[offset];
  631. dc[i]->octetDeltaCount = htonl (flow->octets[i]);
  632. dc[i]->packetDeltaCount = htonl (flow->packets[i]);
  633. dc[i]->ingressInterface = dc[i]->egressInterface = htonl (ifidx);
  634. dc[i]->flowDirection = i;
  635. dc[i]->flowEndReason = flow->flowEndReason;
  636. #ifdef ENABLE_IFNAME
  637. strncpy (dc[i]->interfaceName, option->interfaceName,
  638. strlen (option->interfaceName) <
  639. sizeof (dc[i]->interfaceName) ?
  640. strlen (option->interfaceName) : sizeof (dc[i]->interfaceName));
  641. #endif
  642. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_COMMON);
  643. if (flow->protocol != IPPROTO_ICMP && flow->protocol != IPPROTO_ICMPV6) {
  644. dtr[i] = (struct IPFIX_SOFTFLOWD_DATA_TRANSPORT *) &packet[offset];
  645. dtr[i]->sourceTransportPort = flow->port[i];
  646. dtr[i]->destinationTransportPort = flow->port[i ^ 1];
  647. dtr[i]->protocolIdentifier = flow->protocol;
  648. dtr[i]->tcpControlBits = flow->tcp_flags[i];
  649. dtr[i]->ipClassOfService = flow->tos[i];
  650. dtr[i]->ipVersion = (flow->af == AF_INET) ? 4 : 6;
  651. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_TRANSPORT);
  652. } else {
  653. di[i] = (struct IPFIX_SOFTFLOWD_DATA_ICMP *) &packet[offset];
  654. di[i]->icmpTypeCode = flow->port[i ^ 1];
  655. di[i]->protocolIdentifier = flow->protocol;
  656. di[i]->ipClassOfService = flow->tos[i];
  657. di[i]->ipVersion = (flow->af == AF_INET) ? 4 : 6;
  658. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_ICMP);
  659. }
  660. if (param->track_level >= TRACK_FULL_VLAN) {
  661. dv[i] = (struct IPFIX_SOFTFLOWD_DATA_VLAN *) &packet[offset];
  662. dv[i]->vlanId = htons (flow->vlanid[i]);
  663. dv[i]->postVlanId = htons (flow->vlanid[i ^ 1]);
  664. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_VLAN);
  665. }
  666. if (param->track_level >= TRACK_FULL_VLAN_ETHER) {
  667. de[i] = (struct IPFIX_SOFTFLOWD_DATA_ETHER *) &packet[offset];
  668. memcpy (&de[i]->sourceMacAddress, &flow->ethermac[i], 6);
  669. memcpy (&de[i]->destinationMacAddress, &flow->ethermac[i ^ 1], 6);
  670. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_ETHER);
  671. }
  672. if (bi_flag && i == 0) {
  673. dbc = (struct IPFIX_SOFTFLOWD_DATA_BICOMMON *) &packet[offset];
  674. dbc->octetDeltaCount = htonl (flow->octets[1]);
  675. dbc->packetDeltaCount = htonl (flow->packets[1]);
  676. dbc->ipClassOfService = flow->tos[1];
  677. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_BICOMMON);
  678. if (flow->protocol != IPPROTO_ICMP && flow->protocol != IPPROTO_ICMPV6) {
  679. dbtr = (struct IPFIX_SOFTFLOWD_DATA_BITRANSPORT *)
  680. &packet[offset];
  681. dbtr->tcpControlBits = flow->tcp_flags[1];
  682. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_BITRANSPORT);
  683. } else {
  684. dbi = (struct IPFIX_SOFTFLOWD_DATA_BIICMP *)
  685. &packet[offset];
  686. dbi->icmpTypeCode = flow->port[1];
  687. offset += sizeof (struct IPFIX_SOFTFLOWD_DATA_BIICMP);
  688. }
  689. }
  690. for (k = 0; k < param->max_num_label; k++) {
  691. memcpy (&packet[offset], &flow->mplsLabels[k],
  692. IPFIX_mplsLabelStackSection_SIZE);
  693. offset += IPFIX_mplsLabelStackSection_SIZE;
  694. }
  695. }
  696. *len_used = offset;
  697. return (nflows);
  698. }
  699. static int
  700. valuate_icmp (struct FLOW *flow) {
  701. if (flow == NULL)
  702. return -1;
  703. if (flow->af == AF_INET)
  704. if (flow->protocol == IPPROTO_ICMP)
  705. return 1;
  706. else
  707. return 0;
  708. else if (flow->af == AF_INET6)
  709. if (flow->protocol == IPPROTO_ICMPV6)
  710. return 1;
  711. else
  712. return 0;
  713. else
  714. return -1;
  715. return -1;
  716. }
  717. void
  718. ipfix_resend_template (void) {
  719. if (ipfix_pkts_until_template > 0)
  720. ipfix_pkts_until_template = 0;
  721. }
  722. void
  723. memcpy_template (u_char * packet, u_int * offset,
  724. struct IPFIX_SOFTFLOWD_TEMPLATE *template, u_int8_t bi_flag,
  725. u_int8_t max_num_label) {
  726. int i = 0;
  727. int size = ntohs (template->h.c.length) -
  728. template->bi_count * sizeof (struct IPFIX_VENDOR_FIELD_SPECIFIER) -
  729. max_num_label * sizeof (struct IPFIX_FIELD_SPECIFIER);
  730. memcpy (packet + *offset, template, size);
  731. *offset += size;
  732. if (bi_flag) {
  733. size = template->bi_count * sizeof (struct IPFIX_VENDOR_FIELD_SPECIFIER);
  734. memcpy (packet + *offset, template->v, size);
  735. *offset += size;
  736. }
  737. // mpls
  738. for (i = 0; i < max_num_label; i++) {
  739. struct IPFIX_FIELD_SPECIFIER *mpls_fs =
  740. (struct IPFIX_FIELD_SPECIFIER *) &packet[*offset];
  741. mpls_fs->ie = htons (IPFIX_mplsTopLabelStackSection + i);
  742. mpls_fs->length = htons (IPFIX_mplsLabelStackSection_SIZE);
  743. *offset += sizeof (struct IPFIX_FIELD_SPECIFIER);
  744. }
  745. }
  746. /*
  747. * Given an array of expired flows, send ipfix report packets
  748. * Returns number of packets sent or -1 on error
  749. */
  750. static int
  751. send_ipfix_common (struct FLOW **flows, int num_flows,
  752. struct NETFLOW_TARGET *target,
  753. u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  754. int verbose_flag, u_int8_t bi_flag, u_int16_t version) {
  755. struct IPFIX_HEADER *ipfix;
  756. struct NFLOW9_HEADER *nf9;
  757. struct IPFIX_SET_HEADER *dh;
  758. struct timeval now;
  759. u_int offset, last_af, i, j, num_packets, inc, last_valid, tmplindex;
  760. int8_t icmp_flag, last_icmp_flag;
  761. int r;
  762. u_int records;
  763. u_char packet[IPFIX_SOFTFLOWD_MAX_PACKET_SIZE];
  764. struct timeval *system_boot_time = &param->system_boot_time;
  765. u_int64_t *flows_exported = &param->flows_exported;
  766. u_int64_t *records_sent = &param->records_sent;
  767. struct OPTION *option = &param->option;
  768. static u_int sequence = 1;
  769. if (version != 9 && version != 10)
  770. return (-1);
  771. if (param->adjust_time)
  772. now = param->last_packet_time;
  773. else
  774. gettimeofday (&now, NULL);
  775. if (ipfix_pkts_until_template == -1) {
  776. ipfix_init_template (param, bi_flag, version);
  777. ipfix_pkts_until_template = 0;
  778. if (option != NULL) {
  779. if (version == 10) {
  780. ipfix_init_option (system_boot_time, option);
  781. } else {
  782. nflow9_init_option (ifidx, option);
  783. }
  784. }
  785. }
  786. last_valid = num_packets = 0;
  787. for (j = 0; j < num_flows;) {
  788. memset (packet, 0, sizeof (packet));
  789. if (version == 10) {
  790. ipfix = (struct IPFIX_HEADER *) packet;
  791. ipfix->version = htons (version);
  792. ipfix->length = 0; /* Filled as we go, htons at end */
  793. if (param->adjust_time)
  794. ipfix->export_time = htonl (now.tv_sec);
  795. else
  796. ipfix->export_time = htonl (time (NULL));
  797. ipfix->od_id = 0;
  798. offset = sizeof (*ipfix);
  799. } else if (version == 9) {
  800. nf9 = (struct NFLOW9_HEADER *) packet;
  801. nf9->version = htons (version);
  802. nf9->flows = 0; /* Filled as we go, htons at end */
  803. nf9->uptime_ms = htonl (timeval_sub_ms (&now, system_boot_time));
  804. if (param->adjust_time)
  805. nf9->export_time = htonl (now.tv_sec);
  806. else
  807. nf9->export_time = htonl (time (NULL));
  808. nf9->od_id = 0;
  809. offset = sizeof (*nf9);
  810. }
  811. /* Refresh template headers if we need to */
  812. if (ipfix_pkts_until_template <= 0) {
  813. for (i = 0; i < TMPLMAX; i++) {
  814. memcpy_template (packet, &offset, &templates[i], bi_flag,
  815. param->max_num_label);
  816. }
  817. if (option != NULL) {
  818. u_int16_t opt_tmpl_len = ntohs (option_template.h.c.length);
  819. memcpy (packet + offset, &option_template, opt_tmpl_len);
  820. offset += opt_tmpl_len;
  821. if (version == 10) {
  822. memcpy (packet + offset, &option_data, sizeof (option_data));
  823. offset += sizeof (option_data);
  824. } else if (version == 9) {
  825. memcpy (packet + offset, &nf9opt_data, sizeof (nf9opt_data));
  826. offset += sizeof (nf9opt_data);
  827. }
  828. }
  829. ipfix_pkts_until_template = IPFIX_DEFAULT_TEMPLATE_INTERVAL;
  830. if (target->is_loadbalance && target->num_destinations > 1) {
  831. if (version == 10) {
  832. ipfix->length = htons (offset);
  833. ipfix->sequence =
  834. htonl ((u_int32_t) (*records_sent & 0x00000000ffffffff));
  835. } else if (version == 9) {
  836. nf9->flows = htons (records);
  837. nf9->sequence = htonl (sequence++);
  838. }
  839. if (send_multi_destinations
  840. (target->num_destinations, target->destinations, 0, packet,
  841. offset) < 0)
  842. return (-1);
  843. offset = version == 10 ? sizeof (*ipfix) : sizeof (*nf9); // resest offset
  844. }
  845. }
  846. dh = NULL;
  847. last_af = 0;
  848. last_icmp_flag = -1;
  849. records = 0;
  850. for (i = 0; i + j < num_flows; i++) {
  851. icmp_flag = valuate_icmp (flows[i + j]);
  852. if (dh == NULL || flows[i + j]->af != last_af ||
  853. icmp_flag != last_icmp_flag) {
  854. if (dh != NULL) {
  855. if (offset % 4 != 0) {
  856. /* Pad to multiple of 4 */
  857. dh->length += 4 - (offset % 4);
  858. offset += 4 - (offset % 4);
  859. }
  860. /* Finalise last header */
  861. dh->length = htons (dh->length);
  862. }
  863. if (offset + sizeof (*dh) > sizeof (packet)) {
  864. /* Mark header is finished */
  865. dh = NULL;
  866. break;
  867. }
  868. dh = (struct IPFIX_SET_HEADER *) (packet + offset);
  869. tmplindex = ipfix_flow_to_template_index (flows[i + j]);
  870. dh->set_id = templates[tmplindex].h.r.template_id;
  871. last_af = flows[i + j]->af;
  872. last_icmp_flag = icmp_flag;
  873. last_valid = offset;
  874. dh->length = sizeof (*dh); /* Filled as we go */
  875. offset += sizeof (*dh);
  876. }
  877. r = ipfix_flow_to_flowset (flows[i + j],
  878. packet + offset,
  879. sizeof (packet) - offset,
  880. ifidx, system_boot_time,
  881. &inc, param, bi_flag);
  882. if (r <= 0) {
  883. /* yank off data header, if we had to go back */
  884. if (last_valid)
  885. offset = last_valid;
  886. break;
  887. }
  888. records += (u_int) r;
  889. offset += inc;
  890. dh->length += inc;
  891. last_valid = 0; /* Don't clobber this header now */
  892. if (verbose_flag) {
  893. logit (LOG_DEBUG, "Flow %d/%d: "
  894. "r %d offset %d ie %04x len %d(0x%04x)",
  895. r, i, j, offset, dh->set_id, dh->length, dh->length);
  896. }
  897. }
  898. /* Don't finish header if it has already been done */
  899. if (dh != NULL) {
  900. if (offset % 4 != 0) {
  901. /* Pad to multiple of 4 */
  902. dh->length += 4 - (offset % 4);
  903. offset += 4 - (offset % 4);
  904. }
  905. /* Finalise last header */
  906. dh->length = htons (dh->length);
  907. }
  908. *records_sent += records;
  909. if (version == 10) {
  910. ipfix->length = htons (offset);
  911. ipfix->sequence =
  912. htonl ((u_int32_t) (*records_sent & 0x00000000ffffffff));
  913. } else if (version == 9) {
  914. nf9->flows = htons (records);
  915. nf9->sequence = htonl (sequence++);
  916. }
  917. if (verbose_flag)
  918. logit (LOG_DEBUG, "Sending flow packet len = %d", offset);
  919. if (send_multi_destinations
  920. (target->num_destinations, target->destinations,
  921. target->is_loadbalance, packet, offset) < 0)
  922. return (-1);
  923. num_packets++;
  924. ipfix_pkts_until_template--;
  925. j += i;
  926. }
  927. *flows_exported += j;
  928. param->packets_sent += num_packets;
  929. #ifdef ENABLE_PTHREAD
  930. if (use_thread)
  931. free (flows);
  932. #endif /* ENABLE_PTHREAD */
  933. return (num_packets);
  934. }
  935. int
  936. send_nflow9 (struct SENDPARAMETER sp) {
  937. return send_ipfix_common (sp.flows, sp.num_flows, sp.target, sp.ifidx,
  938. sp.param, sp.verbose_flag, 0, 9);
  939. }
  940. int
  941. send_ipfix (struct SENDPARAMETER sp) {
  942. return send_ipfix_common (sp.flows, sp.num_flows, sp.target, sp.ifidx,
  943. sp.param, sp.verbose_flag, 0, 10);
  944. }
  945. int
  946. send_ipfix_bi (struct SENDPARAMETER sp) {
  947. return send_ipfix_common (sp.flows, sp.num_flows, sp.target, sp.ifidx,
  948. sp.param, sp.verbose_flag, 1, 10);
  949. }