ipfix.c 34 KB

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