cherry-pick.softflowd-0.9.9-3-gbd8e31e.fix-bug.patch 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. Subject: Fix bug. The sequence number field in NetFlow version 9 is number of exported packets. Older version used number of exported flows for this field
  2. Origin: softflowd-0.9.9-3-gbd8e31e <https://github.com/irino/softflowd/commit/softflowd-0.9.9-3-gbd8e31e>
  3. Upstream-Author: Hitoshi Irino <hitoshi.irino@gmail.com>
  4. Date: Sat Sep 29 22:35:18 2012 +0900
  5. --- a/netflow1.c
  6. +++ b/netflow1.c
  7. @@ -60,9 +60,9 @@
  8. * Returns number of packets sent or -1 on error
  9. */
  10. int
  11. -send_netflow_v1(struct FLOW **flows, int num_flows, int nfsock, u_int16_t ifidx,
  12. - u_int64_t *flows_exported, struct timeval *system_boot_time,
  13. - int verbose_flag, struct OPTION *option)
  14. +send_netflow_v1(struct FLOW **flows, int num_flows, int nfsock,
  15. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  16. + int verbose_flag)
  17. {
  18. struct timeval now;
  19. u_int32_t uptime_ms;
  20. @@ -71,6 +71,8 @@
  21. struct NF1_FLOW *flw = NULL;
  22. int i, j, offset, num_packets, err;
  23. socklen_t errsz;
  24. + struct timeval *system_boot_time = &param->system_boot_time;
  25. + u_int64_t *flows_exported = &param->flows_exported;
  26. gettimeofday(&now, NULL);
  27. uptime_ms = timeval_sub_ms(&now, system_boot_time);
  28. --- a/netflow5.c
  29. +++ b/netflow5.c
  30. @@ -59,9 +59,9 @@
  31. * Returns number of packets sent or -1 on error
  32. */
  33. int
  34. -send_netflow_v5(struct FLOW **flows, int num_flows, int nfsock, u_int16_t ifidx,
  35. - u_int64_t *flows_exported, struct timeval *system_boot_time,
  36. - int verbose_flag, struct OPTION *option)
  37. +send_netflow_v5(struct FLOW **flows, int num_flows, int nfsock,
  38. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  39. + int verbose_flag)
  40. {
  41. struct timeval now;
  42. u_int32_t uptime_ms;
  43. @@ -70,6 +70,9 @@
  44. struct NF5_FLOW *flw = NULL;
  45. int i, j, offset, num_packets, err;
  46. socklen_t errsz;
  47. + struct timeval *system_boot_time = &param->system_boot_time;
  48. + u_int64_t *flows_exported = &param->flows_exported;
  49. + struct OPTION *option = &param->option;
  50. gettimeofday(&now, NULL);
  51. uptime_ms = timeval_sub_ms(&now, system_boot_time);
  52. --- a/netflow9.c
  53. +++ b/netflow9.c
  54. @@ -316,9 +316,9 @@
  55. * Returns number of packets sent or -1 on error
  56. */
  57. int
  58. -send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock, u_int16_t ifidx,
  59. - u_int64_t *flows_exported, struct timeval *system_boot_time,
  60. - int verbose_flag, struct OPTION *option)
  61. +send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock,
  62. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  63. + int verbose_flag)
  64. {
  65. struct NF9_HEADER *nf9;
  66. struct NF9_DATA_FLOWSET_HEADER *dh;
  67. @@ -327,6 +327,10 @@
  68. socklen_t errsz;
  69. int err, r;
  70. u_char packet[NF9_SOFTFLOWD_MAX_PACKET_SIZE];
  71. + struct timeval *system_boot_time = &param->system_boot_time;
  72. + u_int64_t *flows_exported = &param->flows_exported;
  73. + u_int64_t *packets_sent = &param->packets_sent;
  74. + struct OPTION *option = &param->option;
  75. gettimeofday(&now, NULL);
  76. @@ -347,7 +351,6 @@
  77. nf9->flows = 0; /* Filled as we go, htons at end */
  78. nf9->uptime_ms = htonl(timeval_sub_ms(&now, system_boot_time));
  79. nf9->time_sec = htonl(time(NULL));
  80. - nf9->package_sequence = htonl(*flows_exported + j);
  81. nf9->source_id = 0;
  82. offset = sizeof(*nf9);
  83. @@ -432,6 +435,7 @@
  84. dh->c.length = htons(dh->c.length);
  85. }
  86. nf9->flows = htons(nf9->flows);
  87. + nf9->package_sequence = htonl(*packets_sent + num_packets + 1);
  88. if (verbose_flag)
  89. logit(LOG_DEBUG, "Sending flow packet len = %d", offset);
  90. --- a/softflowd.c
  91. +++ b/softflowd.c
  92. @@ -95,7 +95,7 @@
  93. /* Netflow send functions */
  94. typedef int (netflow_send_func_t)(struct FLOW **, int, int, u_int16_t,
  95. - u_int64_t *, struct timeval *, int, struct OPTION *);
  96. + struct FLOWTRACKPARAMETERS *, int);
  97. struct NETFLOW_SENDER {
  98. int version;
  99. netflow_send_func_t *func;
  100. @@ -459,9 +459,9 @@
  101. }
  102. /* Flows over maximum life seconds */
  103. - if (ft->maximum_lifetime != 0 &&
  104. + if (ft->param.maximum_lifetime != 0 &&
  105. flow->flow_last.tv_sec - flow->flow_start.tv_sec >
  106. - ft->maximum_lifetime) {
  107. + ft->param.maximum_lifetime) {
  108. flow->expiry->expires_at = 0;
  109. flow->expiry->reason = R_MAXLIFE;
  110. goto out;
  111. @@ -469,60 +469,60 @@
  112. if (flow->protocol == IPPROTO_TCP) {
  113. /* Reset TCP flows */
  114. - if (ft->tcp_rst_timeout != 0 &&
  115. + if (ft->param.tcp_rst_timeout != 0 &&
  116. ((flow->tcp_flags[0] & TH_RST) ||
  117. (flow->tcp_flags[1] & TH_RST))) {
  118. flow->expiry->expires_at = flow->flow_last.tv_sec +
  119. - ft->tcp_rst_timeout;
  120. + ft->param.tcp_rst_timeout;
  121. flow->expiry->reason = R_TCP_RST;
  122. goto out;
  123. }
  124. /* Finished TCP flows */
  125. - if (ft->tcp_fin_timeout != 0 &&
  126. + if (ft->param.tcp_fin_timeout != 0 &&
  127. ((flow->tcp_flags[0] & TH_FIN) &&
  128. (flow->tcp_flags[1] & TH_FIN))) {
  129. flow->expiry->expires_at = flow->flow_last.tv_sec +
  130. - ft->tcp_fin_timeout;
  131. + ft->param.tcp_fin_timeout;
  132. flow->expiry->reason = R_TCP_FIN;
  133. goto out;
  134. }
  135. /* TCP flows */
  136. - if (ft->tcp_timeout != 0) {
  137. + if (ft->param.tcp_timeout != 0) {
  138. flow->expiry->expires_at = flow->flow_last.tv_sec +
  139. - ft->tcp_timeout;
  140. + ft->param.tcp_timeout;
  141. flow->expiry->reason = R_TCP;
  142. goto out;
  143. }
  144. }
  145. - if (ft->udp_timeout != 0 && flow->protocol == IPPROTO_UDP) {
  146. + if (ft->param.udp_timeout != 0 && flow->protocol == IPPROTO_UDP) {
  147. /* UDP flows */
  148. flow->expiry->expires_at = flow->flow_last.tv_sec +
  149. - ft->udp_timeout;
  150. + ft->param.udp_timeout;
  151. flow->expiry->reason = R_UDP;
  152. goto out;
  153. }
  154. - if (ft->icmp_timeout != 0 &&
  155. + if (ft->param.icmp_timeout != 0 &&
  156. ((flow->af == AF_INET && flow->protocol == IPPROTO_ICMP) ||
  157. ((flow->af == AF_INET6 && flow->protocol == IPPROTO_ICMPV6)))) {
  158. /* ICMP flows */
  159. flow->expiry->expires_at = flow->flow_last.tv_sec +
  160. - ft->icmp_timeout;
  161. + ft->param.icmp_timeout;
  162. flow->expiry->reason = R_ICMP;
  163. goto out;
  164. }
  165. /* Everything else */
  166. flow->expiry->expires_at = flow->flow_last.tv_sec +
  167. - ft->general_timeout;
  168. + ft->param.general_timeout;
  169. flow->expiry->reason = R_GENERAL;
  170. out:
  171. - if (ft->maximum_lifetime != 0 && flow->expiry->expires_at != 0) {
  172. + if (ft->param.maximum_lifetime != 0 && flow->expiry->expires_at != 0) {
  173. flow->expiry->expires_at = MIN(flow->expiry->expires_at,
  174. - flow->flow_start.tv_sec + ft->maximum_lifetime);
  175. + flow->flow_start.tv_sec + ft->param.maximum_lifetime);
  176. }
  177. EXPIRY_INSERT(EXPIRIES, &ft->expiries, flow->expiry);
  178. @@ -550,7 +550,7 @@
  179. struct FLOW tmp, *flow;
  180. int frag;
  181. - ft->total_packets++;
  182. + ft->param.total_packets++;
  183. /* Convert the IP packet to a flow identity */
  184. memset(&tmp, 0, sizeof(tmp));
  185. @@ -565,15 +565,15 @@
  186. break;
  187. default:
  188. bad:
  189. - ft->bad_packets++;
  190. + ft->param.bad_packets++;
  191. return (PP_BAD_PACKET);
  192. }
  193. if (frag)
  194. - ft->frag_packets++;
  195. + ft->param.frag_packets++;
  196. /* Zero out bits of the flow that aren't relevant to tracking level */
  197. - switch (ft->track_level) {
  198. + switch (ft->param.track_level) {
  199. case TRACK_IP_ONLY:
  200. tmp.protocol = 0;
  201. /* FALLTHROUGH */
  202. @@ -596,7 +596,7 @@
  203. memcpy(flow, &tmp, sizeof(*flow));
  204. memcpy(&flow->flow_start, received_time,
  205. sizeof(flow->flow_start));
  206. - flow->flow_seq = ft->next_flow_seq++;
  207. + flow->flow_seq = ft->param.next_flow_seq++;
  208. FLOW_INSERT(FLOWS, &ft->flows, flow);
  209. /* Allocate and fill in the associated expiry event */
  210. @@ -611,7 +611,7 @@
  211. flow->expiry->reason = R_GENERAL;
  212. EXPIRY_INSERT(EXPIRIES, &ft->expiries, flow->expiry);
  213. - ft->num_flows++;
  214. + ft->param.num_flows++;
  215. if (verbose_flag)
  216. logit(LOG_DEBUG, "ADD FLOW %s",
  217. format_flow_brief(flow));
  218. @@ -671,8 +671,8 @@
  219. double tmp;
  220. static double n = 1.0;
  221. - ft->flows_expired++;
  222. - ft->flows_pp[flow->protocol % 256]++;
  223. + ft->param.flows_expired++;
  224. + ft->param.flows_pp[flow->protocol % 256]++;
  225. tmp = (double)flow->flow_last.tv_sec +
  226. ((double)flow->flow_last.tv_usec / 1000000.0);
  227. @@ -681,17 +681,17 @@
  228. if (tmp < 0.0)
  229. tmp = 0.0;
  230. - update_statistic(&ft->duration, tmp, n);
  231. - update_statistic(&ft->duration_pp[flow->protocol], tmp,
  232. - (double)ft->flows_pp[flow->protocol % 256]);
  233. + update_statistic(&ft->param.duration, tmp, n);
  234. + update_statistic(&ft->param.duration_pp[flow->protocol], tmp,
  235. + (double)ft->param.flows_pp[flow->protocol % 256]);
  236. tmp = flow->octets[0] + flow->octets[1];
  237. - update_statistic(&ft->octets, tmp, n);
  238. - ft->octets_pp[flow->protocol % 256] += tmp;
  239. + update_statistic(&ft->param.octets, tmp, n);
  240. + ft->param.octets_pp[flow->protocol % 256] += tmp;
  241. tmp = flow->packets[0] + flow->packets[1];
  242. - update_statistic(&ft->packets, tmp, n);
  243. - ft->packets_pp[flow->protocol % 256] += tmp;
  244. + update_statistic(&ft->param.packets, tmp, n);
  245. + ft->param.packets_pp[flow->protocol % 256] += tmp;
  246. n++;
  247. }
  248. @@ -701,34 +701,34 @@
  249. {
  250. switch (e->reason) {
  251. case R_GENERAL:
  252. - ft->expired_general++;
  253. + ft->param.expired_general++;
  254. break;
  255. case R_TCP:
  256. - ft->expired_tcp++;
  257. + ft->param.expired_tcp++;
  258. break;
  259. case R_TCP_RST:
  260. - ft->expired_tcp_rst++;
  261. + ft->param.expired_tcp_rst++;
  262. break;
  263. case R_TCP_FIN:
  264. - ft->expired_tcp_fin++;
  265. + ft->param.expired_tcp_fin++;
  266. break;
  267. case R_UDP:
  268. - ft->expired_udp++;
  269. + ft->param.expired_udp++;
  270. break;
  271. case R_ICMP:
  272. - ft->expired_icmp++;
  273. + ft->param.expired_icmp++;
  274. break;
  275. case R_MAXLIFE:
  276. - ft->expired_maxlife++;
  277. + ft->param.expired_maxlife++;
  278. break;
  279. case R_OVERBYTES:
  280. - ft->expired_overbytes++;
  281. + ft->param.expired_overbytes++;
  282. break;
  283. case R_OVERFLOWS:
  284. - ft->expired_maxflows++;
  285. + ft->param.expired_maxflows++;
  286. break;
  287. case R_FLUSH:
  288. - ft->expired_flush++;
  289. + ft->param.expired_flush++;
  290. break;
  291. }
  292. }
  293. @@ -754,9 +754,9 @@
  294. return (0); /* Now */
  295. /* Cluster expiries by expiry_interval */
  296. - if (ft->expiry_interval > 1) {
  297. - if ((fudge = expires_at % ft->expiry_interval) > 0)
  298. - expires_at += ft->expiry_interval - fudge;
  299. + if (ft->param.expiry_interval > 1) {
  300. + if ((fudge = expires_at % ft->param.expiry_interval) > 0)
  301. + expires_at += ft->param.expiry_interval - fudge;
  302. }
  303. if (expires_at < now.tv_sec)
  304. @@ -799,10 +799,10 @@
  305. (expiry->expires_at < now.tv_sec))) {
  306. /* Flow has expired */
  307. - if (ft->maximum_lifetime != 0 &&
  308. + if (ft->param.maximum_lifetime != 0 &&
  309. expiry->flow->flow_last.tv_sec -
  310. expiry->flow->flow_start.tv_sec >=
  311. - ft->maximum_lifetime)
  312. + ft->param.maximum_lifetime)
  313. expiry->reason = R_MAXLIFE;
  314. if (verbose_flag)
  315. @@ -834,7 +834,7 @@
  316. expiry->flow->expiry = NULL;
  317. expiry_put(ft, expiry);
  318. - ft->num_flows--;
  319. + ft->param.num_flows--;
  320. }
  321. }
  322. @@ -846,15 +846,14 @@
  323. if (num_expired > 0) {
  324. if (target != NULL && target->fd != -1) {
  325. r = target->dialect->func(expired_flows, num_expired,
  326. - target->fd, if_index, &ft->flows_exported,
  327. - &ft->system_boot_time, verbose_flag, &ft->option);
  328. + target->fd, if_index, &ft->param, verbose_flag);
  329. if (verbose_flag)
  330. logit(LOG_DEBUG, "sent %d netflow packets", r);
  331. if (r > 0) {
  332. - ft->packets_sent += r;
  333. + ft->param.packets_sent += r;
  334. /* XXX what if r < num_expired * 2 ? */
  335. } else {
  336. - ft->flows_dropped += num_expired * 2;
  337. + ft->param.flows_dropped += num_expired * 2;
  338. }
  339. }
  340. for (i = 0; i < num_expired; i++) {
  341. @@ -906,7 +905,7 @@
  342. EXPIRY_FOREACH(expiry, EXPIRIES, &ft->expiries) {
  343. expiry->expires_at = 0;
  344. expiry->reason = R_OVERFLOWS;
  345. - ft->flows_force_expired++;
  346. + ft->param.flows_force_expired++;
  347. }
  348. return;
  349. }
  350. @@ -930,7 +929,7 @@
  351. expiryv[i]->reason = R_OVERFLOWS;
  352. EXPIRY_INSERT(EXPIRIES, &ft->expiries, expiryv[i]);
  353. }
  354. - ft->flows_force_expired += num_to_expire;
  355. + ft->param.flows_force_expired += num_to_expire;
  356. free(expiryv);
  357. /* XXX - this is overcomplicated, perhaps use a separate queue */
  358. }
  359. @@ -950,7 +949,7 @@
  360. EXPIRY_REMOVE(EXPIRIES, &ft->expiries, flow->expiry);
  361. expiry_put(ft, flow->expiry);
  362. - ft->num_flows--;
  363. + ft->param.num_flows--;
  364. flow_put(ft, flow);
  365. i++;
  366. }
  367. @@ -971,18 +970,18 @@
  368. char proto[32];
  369. struct pcap_stat ps;
  370. - fprintf(out, "Number of active flows: %d\n", ft->num_flows);
  371. - fprintf(out, "Packets processed: %"PRIu64"\n", ft->total_packets);
  372. - if (ft->non_sampled_packets)
  373. + fprintf(out, "Number of active flows: %d\n", ft->param.num_flows);
  374. + fprintf(out, "Packets processed: %"PRIu64"\n", ft->param.total_packets);
  375. + if (ft->param.non_sampled_packets)
  376. fprintf(out, "Packets non-sampled: %"PRIu64"\n",
  377. - ft->non_sampled_packets);
  378. - fprintf(out, "Fragments: %"PRIu64"\n", ft->frag_packets);
  379. + ft->param.non_sampled_packets);
  380. + fprintf(out, "Fragments: %"PRIu64"\n", ft->param.frag_packets);
  381. fprintf(out, "Ignored packets: %"PRIu64" (%"PRIu64" non-IP, %"PRIu64" too short)\n",
  382. - ft->non_ip_packets + ft->bad_packets, ft->non_ip_packets, ft->bad_packets);
  383. + ft->param.non_ip_packets + ft->param.bad_packets, ft->param.non_ip_packets, ft->param.bad_packets);
  384. fprintf(out, "Flows expired: %"PRIu64" (%"PRIu64" forced)\n",
  385. - ft->flows_expired, ft->flows_force_expired);
  386. + ft->param.flows_expired, ft->param.flows_force_expired);
  387. fprintf(out, "Flows exported: %"PRIu64" in %"PRIu64" packets (%"PRIu64" failures)\n",
  388. - ft->flows_exported, ft->packets_sent, ft->flows_dropped);
  389. + ft->param.flows_exported, ft->param.packets_sent, ft->param.flows_dropped);
  390. if (pcap_stats(pcap, &ps) == 0) {
  391. fprintf(out, "Packets received by libpcap: %lu\n",
  392. @@ -995,43 +994,43 @@
  393. fprintf(out, "\n");
  394. - if (ft->flows_expired != 0) {
  395. + if (ft->param.flows_expired != 0) {
  396. fprintf(out, "Expired flow statistics: minimum average maximum\n");
  397. fprintf(out, " Flow bytes: %12.0f %12.0f %12.0f\n",
  398. - ft->octets.min, ft->octets.mean, ft->octets.max);
  399. + ft->param.octets.min, ft->param.octets.mean, ft->param.octets.max);
  400. fprintf(out, " Flow packets: %12.0f %12.0f %12.0f\n",
  401. - ft->packets.min, ft->packets.mean, ft->packets.max);
  402. + ft->param.packets.min, ft->param.packets.mean, ft->param.packets.max);
  403. fprintf(out, " Duration: %12.2fs %12.2fs %12.2fs\n",
  404. - ft->duration.min, ft->duration.mean, ft->duration.max);
  405. + ft->param.duration.min, ft->param.duration.mean, ft->param.duration.max);
  406. fprintf(out, "\n");
  407. fprintf(out, "Expired flow reasons:\n");
  408. fprintf(out, " tcp = %9"PRIu64" tcp.rst = %9"PRIu64" "
  409. - "tcp.fin = %9"PRIu64"\n", ft->expired_tcp, ft->expired_tcp_rst,
  410. - ft->expired_tcp_fin);
  411. + "tcp.fin = %9"PRIu64"\n", ft->param.expired_tcp, ft->param.expired_tcp_rst,
  412. + ft->param.expired_tcp_fin);
  413. fprintf(out, " udp = %9"PRIu64" icmp = %9"PRIu64" "
  414. - "general = %9"PRIu64"\n", ft->expired_udp, ft->expired_icmp,
  415. - ft->expired_general);
  416. - fprintf(out, " maxlife = %9"PRIu64"\n", ft->expired_maxlife);
  417. - fprintf(out, "over 2 GiB = %9"PRIu64"\n", ft->expired_overbytes);
  418. - fprintf(out, " maxflows = %9"PRIu64"\n", ft->expired_maxflows);
  419. - fprintf(out, " flushed = %9"PRIu64"\n", ft->expired_flush);
  420. + "general = %9"PRIu64"\n", ft->param.expired_udp, ft->param.expired_icmp,
  421. + ft->param.expired_general);
  422. + fprintf(out, " maxlife = %9"PRIu64"\n", ft->param.expired_maxlife);
  423. + fprintf(out, "over 2 GiB = %9"PRIu64"\n", ft->param.expired_overbytes);
  424. + fprintf(out, " maxflows = %9"PRIu64"\n", ft->param.expired_maxflows);
  425. + fprintf(out, " flushed = %9"PRIu64"\n", ft->param.expired_flush);
  426. fprintf(out, "\n");
  427. fprintf(out, "Per-protocol statistics: Octets "
  428. "Packets Avg Life Max Life\n");
  429. for(i = 0; i < 256; i++) {
  430. - if (ft->packets_pp[i]) {
  431. + if (ft->param.packets_pp[i]) {
  432. pe = getprotobynumber(i);
  433. snprintf(proto, sizeof(proto), "%s (%d)",
  434. pe != NULL ? pe->p_name : "Unknown", i);
  435. fprintf(out, " %17s: %14"PRIu64" %12"PRIu64" %8.2fs "
  436. "%10.2fs\n", proto,
  437. - ft->octets_pp[i],
  438. - ft->packets_pp[i],
  439. - ft->duration_pp[i].mean,
  440. - ft->duration_pp[i].max);
  441. + ft->param.octets_pp[i],
  442. + ft->param.packets_pp[i],
  443. + ft->param.duration_pp[i].mean,
  444. + ft->param.duration_pp[i].max);
  445. }
  446. }
  447. }
  448. @@ -1127,16 +1126,16 @@
  449. struct CB_CTXT *cb_ctxt = (struct CB_CTXT *)user_data;
  450. struct timeval tv;
  451. - if (cb_ctxt->ft->option.sample &&
  452. - (cb_ctxt->ft->total_packets +
  453. - cb_ctxt->ft->non_sampled_packets) %
  454. - cb_ctxt->ft->option.sample > 0) {
  455. - cb_ctxt->ft->non_sampled_packets++;
  456. + if (cb_ctxt->ft->param.option.sample &&
  457. + (cb_ctxt->ft->param.total_packets +
  458. + cb_ctxt->ft->param.non_sampled_packets) %
  459. + cb_ctxt->ft->param.option.sample > 0) {
  460. + cb_ctxt->ft->param.non_sampled_packets++;
  461. return;
  462. }
  463. s = datalink_check(cb_ctxt->linktype, pkt, phdr->caplen, &af);
  464. if (s < 0 || (!cb_ctxt->want_v6 && af == AF_INET6)) {
  465. - cb_ctxt->ft->non_ip_packets++;
  466. + cb_ctxt->ft->param.non_ip_packets++;
  467. } else {
  468. tv.tv_sec = phdr->ts.tv_sec;
  469. tv.tv_usec = phdr->ts.tv_usec;
  470. @@ -1149,14 +1148,14 @@
  471. static void
  472. print_timeouts(struct FLOWTRACK *ft, FILE *out)
  473. {
  474. - fprintf(out, " TCP timeout: %ds\n", ft->tcp_timeout);
  475. - fprintf(out, " TCP post-RST timeout: %ds\n", ft->tcp_rst_timeout);
  476. - fprintf(out, " TCP post-FIN timeout: %ds\n", ft->tcp_fin_timeout);
  477. - fprintf(out, " UDP timeout: %ds\n", ft->udp_timeout);
  478. - fprintf(out, " ICMP timeout: %ds\n", ft->icmp_timeout);
  479. - fprintf(out, " General timeout: %ds\n", ft->general_timeout);
  480. - fprintf(out, " Maximum lifetime: %ds\n", ft->maximum_lifetime);
  481. - fprintf(out, " Expiry interval: %ds\n", ft->expiry_interval);
  482. + fprintf(out, " TCP timeout: %ds\n", ft->param.tcp_timeout);
  483. + fprintf(out, " TCP post-RST timeout: %ds\n", ft->param.tcp_rst_timeout);
  484. + fprintf(out, " TCP post-FIN timeout: %ds\n", ft->param.tcp_fin_timeout);
  485. + fprintf(out, " UDP timeout: %ds\n", ft->param.udp_timeout);
  486. + fprintf(out, " ICMP timeout: %ds\n", ft->param.icmp_timeout);
  487. + fprintf(out, " General timeout: %ds\n", ft->param.general_timeout);
  488. + fprintf(out, " Maximum lifetime: %ds\n", ft->param.maximum_lifetime);
  489. + fprintf(out, " Expiry interval: %ds\n", ft->param.expiry_interval);
  490. }
  491. static int
  492. @@ -1226,7 +1225,7 @@
  493. } else if (strcmp(buf, "statistics") == 0) {
  494. fprintf(ctlf, "softflowd[%u]: Accumulated statistics "
  495. "since %s UTC:\n", (unsigned int)getpid(),
  496. - format_time(ft->system_boot_time.tv_sec));
  497. + format_time(ft->param.system_boot_time.tv_sec));
  498. statistics(ft, ctlf, pcap);
  499. ret = 0;
  500. } else if (strcmp(buf, "debug+") == 0) {
  501. @@ -1430,25 +1429,25 @@
  502. {
  503. /* Set up flow-tracking structure */
  504. memset(ft, '\0', sizeof(*ft));
  505. - ft->next_flow_seq = 1;
  506. + ft->param.next_flow_seq = 1;
  507. FLOW_INIT(&ft->flows);
  508. EXPIRY_INIT(&ft->expiries);
  509. freelist_init(&ft->flow_freelist, sizeof(struct FLOW));
  510. freelist_init(&ft->expiry_freelist, sizeof(struct EXPIRY));
  511. - ft->max_flows = DEFAULT_MAX_FLOWS;
  512. + ft->param.max_flows = DEFAULT_MAX_FLOWS;
  513. - ft->track_level = TRACK_FULL;
  514. + ft->param.track_level = TRACK_FULL;
  515. - ft->tcp_timeout = DEFAULT_TCP_TIMEOUT;
  516. - ft->tcp_rst_timeout = DEFAULT_TCP_RST_TIMEOUT;
  517. - ft->tcp_fin_timeout = DEFAULT_TCP_FIN_TIMEOUT;
  518. - ft->udp_timeout = DEFAULT_UDP_TIMEOUT;
  519. - ft->icmp_timeout = DEFAULT_ICMP_TIMEOUT;
  520. - ft->general_timeout = DEFAULT_GENERAL_TIMEOUT;
  521. - ft->maximum_lifetime = DEFAULT_MAXIMUM_LIFETIME;
  522. - ft->expiry_interval = DEFAULT_EXPIRY_INTERVAL;
  523. + ft->param.tcp_timeout = DEFAULT_TCP_TIMEOUT;
  524. + ft->param.tcp_rst_timeout = DEFAULT_TCP_RST_TIMEOUT;
  525. + ft->param.tcp_fin_timeout = DEFAULT_TCP_FIN_TIMEOUT;
  526. + ft->param.udp_timeout = DEFAULT_UDP_TIMEOUT;
  527. + ft->param.icmp_timeout = DEFAULT_ICMP_TIMEOUT;
  528. + ft->param.general_timeout = DEFAULT_GENERAL_TIMEOUT;
  529. + ft->param.maximum_lifetime = DEFAULT_MAXIMUM_LIFETIME;
  530. + ft->param.expiry_interval = DEFAULT_EXPIRY_INTERVAL;
  531. }
  532. static char *
  533. @@ -1546,28 +1545,28 @@
  534. exit(1);
  535. }
  536. if (strcmp(name, "tcp") == 0)
  537. - ft->tcp_timeout = timeout;
  538. + ft->param.tcp_timeout = timeout;
  539. else if (strcmp(name, "tcp.rst") == 0)
  540. - ft->tcp_rst_timeout = timeout;
  541. + ft->param.tcp_rst_timeout = timeout;
  542. else if (strcmp(name, "tcp.fin") == 0)
  543. - ft->tcp_fin_timeout = timeout;
  544. + ft->param.tcp_fin_timeout = timeout;
  545. else if (strcmp(name, "udp") == 0)
  546. - ft->udp_timeout = timeout;
  547. + ft->param.udp_timeout = timeout;
  548. else if (strcmp(name, "icmp") == 0)
  549. - ft->icmp_timeout = timeout;
  550. + ft->param.icmp_timeout = timeout;
  551. else if (strcmp(name, "general") == 0)
  552. - ft->general_timeout = timeout;
  553. + ft->param.general_timeout = timeout;
  554. else if (strcmp(name, "maxlife") == 0)
  555. - ft->maximum_lifetime = timeout;
  556. + ft->param.maximum_lifetime = timeout;
  557. else if (strcmp(name, "expint") == 0)
  558. - ft->expiry_interval = timeout;
  559. + ft->param.expiry_interval = timeout;
  560. else {
  561. fprintf(stderr, "Invalid -t name.\n");
  562. usage();
  563. exit(1);
  564. }
  565. - if (ft->general_timeout == 0) {
  566. + if (ft->param.general_timeout == 0) {
  567. fprintf(stderr, "\"general\" flow timeout must be "
  568. "greater than zero\n");
  569. exit(1);
  570. @@ -1765,11 +1764,11 @@
  571. break;
  572. case 'T':
  573. if (strcasecmp(optarg, "full") == 0)
  574. - flowtrack.track_level = TRACK_FULL;
  575. + flowtrack.param.track_level = TRACK_FULL;
  576. else if (strcasecmp(optarg, "proto") == 0)
  577. - flowtrack.track_level = TRACK_IP_PROTO;
  578. + flowtrack.param.track_level = TRACK_IP_PROTO;
  579. else if (strcasecmp(optarg, "ip") == 0)
  580. - flowtrack.track_level = TRACK_IP_ONLY;
  581. + flowtrack.param.track_level = TRACK_IP_ONLY;
  582. else {
  583. fprintf(stderr, "Unknown flow tracking "
  584. "level\n");
  585. @@ -1786,7 +1785,7 @@
  586. }
  587. break;
  588. case 'm':
  589. - if ((flowtrack.max_flows = atoi(optarg)) < 0) {
  590. + if ((flowtrack.param.max_flows = atoi(optarg)) < 0) {
  591. fprintf(stderr, "Invalid maximum flows\n\n");
  592. usage();
  593. exit(1);
  594. @@ -1819,9 +1818,9 @@
  595. target.dialect = &nf[i];
  596. break;
  597. case 's':
  598. - flowtrack.option.sample = atoi(optarg);
  599. - if (flowtrack.option.sample < 2) {
  600. - flowtrack.option.sample = 0;
  601. + flowtrack.param.option.sample = atoi(optarg);
  602. + if (flowtrack.param.option.sample < 2) {
  603. + flowtrack.param.option.sample = 0;
  604. }
  605. break;
  606. default:
  607. @@ -1891,7 +1890,7 @@
  608. }
  609. /* Main processing loop */
  610. - gettimeofday(&flowtrack.system_boot_time, NULL);
  611. + gettimeofday(&flowtrack.param.system_boot_time, NULL);
  612. stop_collection_flag = 0;
  613. memset(&cb_ctxt, '\0', sizeof(cb_ctxt));
  614. cb_ctxt.ft = &flowtrack;
  615. @@ -1935,7 +1934,7 @@
  616. /* If we have data, run it through libpcap */
  617. if (!stop_collection_flag &&
  618. (capfile != NULL || pl[0].revents != 0)) {
  619. - r = pcap_dispatch(pcap, flowtrack.max_flows, flow_cb,
  620. + r = pcap_dispatch(pcap, flowtrack.param.max_flows, flow_cb,
  621. (void*)&cb_ctxt);
  622. if (r == -1) {
  623. logit(LOG_ERR, "Exiting on pcap_dispatch: %s",
  624. @@ -1961,7 +1960,7 @@
  625. * or whenever we have exceeded the maximum number of active
  626. * flows
  627. */
  628. - if (flowtrack.num_flows > flowtrack.max_flows ||
  629. + if (flowtrack.param.num_flows > flowtrack.param.max_flows ||
  630. next_expire(&flowtrack) == 0) {
  631. expiry_check:
  632. /*
  633. @@ -1978,9 +1977,9 @@
  634. * If we are over max_flows, force-expire the oldest
  635. * out first and immediately reprocess to evict them
  636. */
  637. - if (flowtrack.num_flows > flowtrack.max_flows) {
  638. + if (flowtrack.param.num_flows > flowtrack.param.max_flows) {
  639. force_expire(&flowtrack,
  640. - flowtrack.num_flows - flowtrack.max_flows);
  641. + flowtrack.param.num_flows - flowtrack.param.max_flows);
  642. goto expiry_check;
  643. }
  644. }
  645. --- a/softflowd.h
  646. +++ b/softflowd.h
  647. @@ -80,19 +80,8 @@
  648. struct OPTION {
  649. uint32_t sample;
  650. };
  651. -/*
  652. - * This structure is the root of the flow tracking system.
  653. - * It holds the root of the tree of active flows and the head of the
  654. - * tree of expiry events. It also collects miscellaneous statistics
  655. - */
  656. -struct FLOWTRACK {
  657. - /* The flows and their expiry events */
  658. - FLOW_HEAD(FLOWS, FLOW) flows; /* Top of flow tree */
  659. - EXPIRY_HEAD(EXPIRIES, EXPIRY) expiries; /* Top of expiries tree */
  660. -
  661. - struct freelist flow_freelist; /* Freelist for flows */
  662. - struct freelist expiry_freelist; /* Freelist for expiry events */
  663. +struct FLOWTRACKPARAMETERS {
  664. unsigned int num_flows; /* # of active flows */
  665. unsigned int max_flows; /* Max # of active flows */
  666. u_int64_t next_flow_seq; /* Next flow ID */
  667. @@ -147,6 +136,21 @@
  668. /* Optional information */
  669. struct OPTION option;
  670. };
  671. +/*
  672. + * This structure is the root of the flow tracking system.
  673. + * It holds the root of the tree of active flows and the head of the
  674. + * tree of expiry events. It also collects miscellaneous statistics
  675. + */
  676. +struct FLOWTRACK {
  677. + /* The flows and their expiry events */
  678. + FLOW_HEAD(FLOWS, FLOW) flows; /* Top of flow tree */
  679. + EXPIRY_HEAD(EXPIRIES, EXPIRY) expiries; /* Top of expiries tree */
  680. +
  681. + struct freelist flow_freelist; /* Freelist for flows */
  682. + struct freelist expiry_freelist; /* Freelist for expiry events */
  683. +
  684. + struct FLOWTRACKPARAMETERS param;
  685. +};
  686. /*
  687. * This structure is an entry in the tree of flows that we are
  688. @@ -212,14 +216,14 @@
  689. /* Prototypes for functions to send NetFlow packets, from netflow*.c */
  690. int send_netflow_v1(struct FLOW **flows, int num_flows, int nfsock,
  691. - u_int16_t ifidx, u_int64_t *flows_exported, struct timeval *system_boot_time,
  692. - int verbose_flag, struct OPTION *option);
  693. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  694. + int verbose_flag);
  695. int send_netflow_v5(struct FLOW **flows, int num_flows, int nfsock,
  696. - u_int16_t ifidx, u_int64_t *flows_exported, struct timeval *system_boot_time,
  697. - int verbose_flag, struct OPTION *option);
  698. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  699. + int verbose_flag);
  700. int send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock,
  701. - u_int16_t ifidx, u_int64_t *flows_exported, struct timeval *system_boot_time,
  702. - int verbose_flag, struct OPTION *option);
  703. + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
  704. + int verbose_flag);
  705. /* Force a resend of the flow template */
  706. void netflow9_resend_template(void);