netflow1.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright 2002 Damien Miller <djm@mindrot.org> All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  14. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  15. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  16. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "common.h"
  25. #include "log.h"
  26. #include "treetype.h"
  27. #include "softflowd.h"
  28. #ifdef ENABLE_LEGACY
  29. /*
  30. * This is the Cisco Netflow(tm) version 1 packet format
  31. * Based on:
  32. * http://www.cisco.com/en/US/products/sw/netmgtsw/ps1964/products_implementation_design_guide09186a00800d6a11.html
  33. */
  34. struct NF1_HEADER {
  35. u_int16_t version, flows;
  36. u_int32_t uptime_ms, time_sec, time_nanosec;
  37. };
  38. struct NF1_FLOW {
  39. u_int32_t src_ip, dest_ip, nexthop_ip;
  40. u_int16_t if_index_in, if_index_out;
  41. u_int32_t flow_packets, flow_octets;
  42. u_int32_t flow_start, flow_finish;
  43. u_int16_t src_port, dest_port;
  44. u_int16_t pad1;
  45. u_int8_t protocol, tos, tcp_flags;
  46. u_int8_t pad2, pad3, pad4;
  47. u_int32_t reserved1;
  48. #if 0
  49. u_int8_t reserved2; /* XXX: no longer used */
  50. #endif
  51. };
  52. /* Maximum of 24 flows per packet */
  53. #define NF1_MAXFLOWS 24
  54. #define NF1_MAXPACKET_SIZE (sizeof(struct NF1_HEADER) + \
  55. (NF1_MAXFLOWS * sizeof(struct NF1_FLOW)))
  56. /*
  57. * Given an array of expired flows, send netflow v1 report packets
  58. * Returns number of packets sent or -1 on error
  59. */
  60. int
  61. send_netflow_v1 (struct SENDPARAMETER sp) {
  62. struct FLOW **flows = sp.flows;
  63. int num_flows = sp.num_flows;
  64. u_int16_t ifidx = sp.ifidx;
  65. struct FLOWTRACKPARAMETERS *param = sp.param;
  66. int verbose_flag = sp.verbose_flag;
  67. struct timeval now;
  68. u_int32_t uptime_ms;
  69. u_int8_t packet[NF1_MAXPACKET_SIZE]; /* Maximum allowed packet size (24 flows) */
  70. struct NF1_HEADER *hdr = NULL;
  71. struct NF1_FLOW *flw = NULL;
  72. int i, j, offset, num_packets;
  73. struct timeval *system_boot_time = &param->system_boot_time;
  74. u_int64_t *flows_exported = &param->flows_exported;
  75. if (param->adjust_time)
  76. now = param->last_packet_time;
  77. else
  78. gettimeofday (&now, NULL);
  79. uptime_ms = timeval_sub_ms (&now, system_boot_time);
  80. hdr = (struct NF1_HEADER *) packet;
  81. for (num_packets = offset = j = i = 0; i < num_flows; i++) {
  82. if (j >= NF1_MAXFLOWS - 1) {
  83. if (verbose_flag)
  84. logit (LOG_DEBUG, "Sending flow packet len = %d", offset);
  85. param->records_sent += hdr->flows;
  86. hdr->flows = htons (hdr->flows);
  87. if (send_multi_destinations
  88. (sp.target->num_destinations, sp.target->destinations,
  89. sp.target->is_loadbalance, packet, offset) < 0)
  90. return (-1);
  91. *flows_exported += j;
  92. j = 0;
  93. num_packets++;
  94. }
  95. if (j == 0) {
  96. memset (&packet, '\0', sizeof (packet));
  97. hdr->version = htons (1);
  98. hdr->flows = 0; /* Filled in as we go */
  99. hdr->uptime_ms = htonl (uptime_ms);
  100. hdr->time_sec = htonl (now.tv_sec);
  101. hdr->time_nanosec = htonl (now.tv_usec * 1000);
  102. offset = sizeof (*hdr);
  103. }
  104. flw = (struct NF1_FLOW *) (packet + offset);
  105. flw->if_index_in = flw->if_index_out = htons (ifidx);
  106. /* NetFlow v.1 doesn't do IPv6 */
  107. if (flows[i]->af != AF_INET)
  108. continue;
  109. if (flows[i]->octets[0] > 0) {
  110. flw->src_ip = flows[i]->addr[0].v4.s_addr;
  111. flw->dest_ip = flows[i]->addr[1].v4.s_addr;
  112. flw->src_port = flows[i]->port[0];
  113. flw->dest_port = flows[i]->port[1];
  114. flw->flow_packets = htonl (flows[i]->packets[0]);
  115. flw->flow_octets = htonl (flows[i]->octets[0]);
  116. flw->flow_start =
  117. htonl (timeval_sub_ms (&flows[i]->flow_start, system_boot_time));
  118. flw->flow_finish =
  119. htonl (timeval_sub_ms (&flows[i]->flow_last, system_boot_time));
  120. flw->protocol = flows[i]->protocol;
  121. flw->tcp_flags = flows[i]->tcp_flags[0];
  122. flw->tos = flows[i]->tos[0];
  123. offset += sizeof (*flw);
  124. j++;
  125. hdr->flows++;
  126. }
  127. flw = (struct NF1_FLOW *) (packet + offset);
  128. flw->if_index_in = flw->if_index_out = htons (ifidx);
  129. if (flows[i]->octets[1] > 0) {
  130. flw->src_ip = flows[i]->addr[1].v4.s_addr;
  131. flw->dest_ip = flows[i]->addr[0].v4.s_addr;
  132. flw->src_port = flows[i]->port[1];
  133. flw->dest_port = flows[i]->port[0];
  134. flw->flow_packets = htonl (flows[i]->packets[1]);
  135. flw->flow_octets = htonl (flows[i]->octets[1]);
  136. flw->flow_start =
  137. htonl (timeval_sub_ms (&flows[i]->flow_start, system_boot_time));
  138. flw->flow_finish =
  139. htonl (timeval_sub_ms (&flows[i]->flow_last, system_boot_time));
  140. flw->protocol = flows[i]->protocol;
  141. flw->tcp_flags = flows[i]->tcp_flags[1];
  142. flw->tos = flows[i]->tos[1];
  143. offset += sizeof (*flw);
  144. j++;
  145. hdr->flows++;
  146. }
  147. }
  148. /* Send any leftovers */
  149. if (j != 0) {
  150. if (verbose_flag)
  151. logit (LOG_DEBUG, "Sending flow packet len = %d", offset);
  152. param->records_sent += hdr->flows;
  153. hdr->flows = htons (hdr->flows);
  154. if (send_multi_destinations
  155. (sp.target->num_destinations, sp.target->destinations,
  156. sp.target->is_loadbalance, packet, offset) < 0)
  157. return (-1);
  158. num_packets++;
  159. }
  160. *flows_exported += j;
  161. param->packets_sent += num_packets;
  162. #ifdef ENABLE_PTHREAD
  163. if (use_thread)
  164. free (sp.flows);
  165. #endif /* ENABLE_PTHREAD */
  166. return (num_packets);
  167. }
  168. #endif /* ENABLE_LEGACY */