--- snort-2.1.2/src/util.c	2004-03-31 20:09:46.000000000 +0200
+++ snort-2.1.2-netflow/src/util.c	2004-04-08 15:59:46.000000000 +0200
@@ -893,6 +893,7 @@
     }
     else
     {
+    if(pv.netflow_port == 0) {
         /* collect the packet stats */
         if(pcap_stats(pd, &ps))
         {
@@ -918,6 +919,34 @@
             {
                 LogMessage(".\n");
             }
+	}
+    } else {
+           LogMessage("\n\n===================================="
+                    "===========================================\n");
+            LogMessage("Snort analyzed %u packets/%u flows NetFlow\n"
+		       "===================================="
+		       "===========================================\n",
+                    pc.netflow_pkts, pc.netflow_flows);
+
+	    recv = pc.tcp+pc.udp+pc.icmp+pc.other;
+	    drop = 0;
+    }
+
+            LogMessage("\n\n===================================="
+                    "===========================================\n");
+            LogMessage("Snort analyzed %u out of %u packets, ", 
+                    ps.ps_recv, ps.ps_recv+ps.ps_drop);
+
+            if(ps.ps_recv)
+            {
+                LogMessage("dropping %u(%.3f%%) packets\n\n", 
+                        ps.ps_drop, 
+                        CalcPct( (float) ps.ps_drop, (float) (ps.ps_recv+ps.ps_drop) ));
+            }
+            else
+            {
+                LogMessage(".\n");
+            }
 
             LogMessage("Breakdown by protocol:                Action Stats:\n");
             LogMessage("    TCP: %-10lu (%.3f%%)%-*sALERTS: %-10lu\n", 
@@ -985,7 +1014,6 @@
             LogMessage("=============================================="
                     "=================================\n");
         }    
-    }
 
     return;
 }
--- snort-2.1.2/src/snort.c	2004-02-04 20:51:12.000000000 +0100
+++ snort-2.1.2-netflow/src/snort.c	2004-04-08 16:01:29.000000000 +0200
@@ -71,6 +71,7 @@
 #include "fpdetect.h"
 #include "sfthreshold.h"
 #include "packet_time.h"
+#include "netflow.h"
 #include "src/preprocessors/flow/flow_print.h"
 #include "src/detection-plugins/sp_flowbits.h"
 
@@ -714,6 +715,7 @@
     FPUTS_BOTH ("        -X         Dump the raw packet data starting at the link layer\n");
     FPUTS_BOTH ("        -y         Include year in timestamp in the alert and log files\n");
     FPUTS_BOTH ("        -z         Set assurance mode, match on established sesions (for TCP)\n");
+    FPUTS_BOTH ("        -5 <port>  Listen on <port> for incoming NetFlow v5 flows (no pcap is used)\n");
     FPUTS_BOTH ("        -?         Show this information\n");
     FPUTS_BOTH ("<Filter Options> are standard BPF options, as seen in TCPDump\n");
 
@@ -766,11 +768,11 @@
 
 #ifndef WIN32
     /* Unix does not support an argument to -s <wink marty!> OR -E, -W */
-    valid_options = "?A:bB:c:CdDefF:g:h:i:Ik:l:L:m:n:NoOpP:qr:R:sS:t:Tu:UvVwXyz";
+    valid_options = "?A:bB:c:CdDefF:g:h:i:Ik:l:L:m:n:NoOpP:qr:R:sS:t:Tu:UvVwXyz5:";
 #else
     /* Win32 does not support:  -D, -g, -m, -t, -u */
     /* Win32 no longer supports an argument to -s, either! */
-    valid_options = "?A:bB:c:CdeEfF:h:i:Ik:l:L:n:NoOpP:qr:R:sS:TUvVwWXyz";
+    valid_options = "?A:bB:c:CdeEfF:h:i:Ik:l:L:n:NoOpP:qr:R:sS:TUvVwWXyz5:";
 #endif
 
     /* loop through each command line var and process it */
@@ -1255,6 +1257,12 @@
                 pv.assurance_mode = ASSURE_EST;
                 break;
 
+            case '5':
+                DEBUG_WRAP(DebugMessage(DEBUG_INIT, "NetFlow v5 support "
+                            "activated\n"););
+                pv.netflow_port = atoi(optarg);
+                break;
+
             case '?':  /* show help and exit */
                 DisplayBanner();
                 ShowUsage(progname);
@@ -1577,17 +1585,119 @@
     bzero((char *) &tz, sizeof(tz));
     gettimeofday(&starttime, &tz);
 
-    /* Read all packets on the device.  Continue until cnt packets read */
-    if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler) ProcessPacket, NULL) < 0)
-    {
-        if(pv.daemon_flag)
+    if(pv.netflow_port > 0) {
+      int inSocket, len;
+      struct sockaddr_in sockIn;
+      char buffer[1600];
+      int sockopt = 1;
+
+      inSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+      setsockopt(inSocket, SOL_SOCKET, SO_REUSEADDR,(char *)&sockopt, sizeof(sockopt));
+
+      sockIn.sin_family            = AF_INET;
+      sockIn.sin_port              =(int)htons(pv.netflow_port);
+      sockIn.sin_addr.s_addr       = INADDR_ANY;
+
+      if(bind(inSocket,(struct sockaddr *)&sockIn, sizeof(sockIn)) < 0) {
+	FatalError("NetFlow collector port %d already in use", pv.netflow_port);
+	close(inSocket);
+	exit(0);
+      } else
+	LogMessage("NetFlow listening on port %d\n", pv.netflow_port);
+
+      while(inSocket > 0) {
+	struct sockaddr_in fromHost;
+	int bufferLen;
+
+	len = sizeof(fromHost);
+	if((bufferLen = recvfrom(inSocket,(char*)&buffer, sizeof(buffer),
+				 0,(struct sockaddr*)&fromHost, &len)) > 0) {
+	  NetFlow5Record the5Record;
+
+
+	  memcpy(&the5Record, buffer, bufferLen > sizeof(the5Record) ? sizeof(the5Record): bufferLen);
+
+	  if(ntohs(the5Record.flowHeader.version) == 5) {
+	    int i, numFlows = ntohs(the5Record.flowHeader.count);
+	    Packet p;
+	    struct pcap_pkthdr pkth;
+	    IPHdr iph;
+	    TCPHdr tcph;
+	    UDPHdr udph;
+
+	    if(numFlows > CONST_V5FLOWS_PER_PAK) numFlows = CONST_V5FLOWS_PER_PAK;
+
+	    pc.netflow_pkts++, pc.netflow_flows += numFlows;
+	    DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Received %d flows\n", numFlows););
+
+	    for(i=0; i<numFlows; i++) {
+	      struct flow_ver5_rec *record = &the5Record.flowRecord[i];
+
+	      memset(&p, 0, sizeof(p));
+
+	      pkth.ts.tv_sec = ntohl(record->Last), pkth.ts.tv_usec = 0,
+		pkth.caplen = 255 /* DUMMY */, pkth.len = 255 /* DUMMY */;
+	      p.pkth = &pkth;
+	      p.iph = &iph;
+
+	      iph.ip_verhl = 0x45 /* IPv4 */;
+	      iph.ip_len = 1024; /* DUMMY */
+	      iph.ip_ttl = 64; /* DUMMY */
+	      iph.ip_len = htons(64);
+	      iph.ip_proto = record->prot;
+	      iph.ip_src.s_addr = record->srcaddr;
+	      iph.ip_dst.s_addr = record->dstaddr;
+
+	      switch(record->prot) {
+	      case IPPROTO_ICMP:
+		pc.icmp += ntohl(record->dOctets);
+		break;
+	      case IPPROTO_TCP:
+		pc.tcp += ntohl(record->dOctets);
+		p.tcph = &tcph;
+		tcph.th_sport = record->srcport;
+		tcph.th_dport = record->dstport;
+		tcph.th_flags = record->tcp_flags; 
+
+		if(tcph.th_flags && TH_ACK) tcph.th_ack = 0x1234; /* DUMMY */
+		tcph.th_win = 32768; /* DUMMY */
+		tcph.th_offx2 = 0xb0; /* DUMMY */
+		p.sp = ntohs(record->srcport), p.dp = ntohs(record->dstport);
+		break;
+	      case IPPROTO_UDP:
+		pc.udp += ntohl(record->dOctets);
+		p.udph = &udph;
+		udph.uh_sport = record->srcport;
+		udph.uh_dport = record->dstport;
+		udph.uh_len   = htons(ntohl(record->dOctets)/ntohl(record->dPkts));
+		p.sp = ntohs(record->srcport), p.dp = ntohs(record->dstport);
+		break;
+	      default:
+		pc.other += ntohl(record->dOctets);
+		break;
+	      }
+
+	      DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Processing flow %d/%d\n", i, numFlows););
+	      Preprocess(&p);
+	    }
+	  }
+	}
+      }
+
+      close(inSocket);
+    } else {
+      /* Read all packets on the device.  Continue until cnt packets read */
+      if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler) ProcessPacket, NULL) < 0)
+	{
+	  if(pv.daemon_flag)
             syslog(LOG_CONS | LOG_DAEMON, "pcap_loop: %s", pcap_geterr(pd));
-        else
+	  else
             ErrorMessage("pcap_loop: %s\n", pcap_geterr(pd));
-
-        CleanExit(1);
+	  
+	  CleanExit(1);
+	}
     }
-
     gettimeofday(&endtime, &tz);
 
     TIMERSUB(&endtime, &starttime, &difftime);
--- snort-2.1.2/src/snort.h	2004-03-31 20:09:46.000000000 +0200
+++ snort-2.1.2-netflow/src/snort.h	2004-04-08 15:55:14.000000000 +0200
@@ -196,6 +196,7 @@
     u_int32_t obfuscation_net;
     u_int32_t obfuscation_mask;
     int alert_mode;
+    u_short netflow_port;
     int log_plugin_active;
     int alert_plugin_active;
     u_int32_t log_bitmap;
@@ -233,6 +234,7 @@
     u_long ipv6;
     u_long ipx;
     u_long discards;
+    u_long netflow_pkts, netflow_flows;
     u_long alert_pkts;
     u_long log_pkts;
     u_long pass_pkts;
--- snort-2.1.2/src/netflow.h	1970-01-01 01:00:00.000000000 +0100
+++ snort-2.1.2-netflow/src/netflow.h	2004-04-08 16:01:59.000000000 +0200
@@ -0,0 +1,72 @@
+/*
+** Copyright (C) 2004 Luca Deri <deri@ntop.org>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __NETFLOW_H__
+#define __NETFLOW_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* ********************************* */
+
+#define CONST_V5FLOWS_PER_PAK 30
+
+struct flow_ver5_hdr {
+  u_int16_t version;         /* Current version=5*/
+  u_int16_t count;           /* The number of records in PDU. */
+  u_int32_t sysUptime;       /* Current time in msecs since router booted */
+  u_int32_t unix_secs;       /* Current seconds since 0000 UTC 1970 */
+  u_int32_t unix_nsecs;      /* Residual nanoseconds since 0000 UTC 1970 */
+  u_int32_t flow_sequence;   /* Sequence number of total flows seen */
+  u_int8_t  engine_type;     /* Type of flow switching engine (RP,VIP,etc.)*/
+  u_int8_t  engine_id;       /* Slot number of the flow switching engine */
+};
+
+struct flow_ver5_rec {
+  u_int32_t srcaddr;    /* Source IP Address */
+  u_int32_t dstaddr;    /* Destination IP Address */
+  u_int32_t nexthop;    /* Next hop router's IP Address */
+  u_int16_t input;      /* Input interface index */
+  u_int16_t output;     /* Output interface index */
+  u_int32_t dPkts;      /* Packets sent in Duration (milliseconds between 1st
+			   & last packet in this flow)*/
+  u_int32_t dOctets;    /* Octets sent in Duration (milliseconds between 1st
+			   & last packet in  this flow)*/
+  u_int32_t First;      /* SysUptime at start of flow */
+  u_int32_t Last;       /* and of last packet of the flow */
+  u_int16_t srcport;    /* TCP/UDP source port number (.e.g, FTP, Telnet, etc.,or equivalent) */
+  u_int16_t dstport;    /* TCP/UDP destination port number (.e.g, FTP, Telnet, etc.,or equivalent) */
+  u_int8_t  pad1;       /* pad to word boundary */
+  u_int8_t  tcp_flags;  /* Cumulative OR of tcp flags */
+  u_int8_t  prot;       /* IP protocol, e.g., 6=TCP, 17=UDP, etc... */
+  u_int8_t  tos;        /* IP Type-of-Service */
+  u_int16_t dst_as;     /* dst peer/origin Autonomous System */
+  u_int16_t src_as;     /* source peer/origin Autonomous System */
+  u_int8_t  dst_mask;   /* destination route's mask bits */
+  u_int8_t  src_mask;   /* source route's mask bits */
+  u_int16_t pad2;       /* pad to word boundary */
+};
+
+typedef struct single_flow_ver5_rec {
+  struct flow_ver5_hdr flowHeader;
+  struct flow_ver5_rec flowRecord[CONST_V5FLOWS_PER_PAK+1 /* safe against buffer overflows */];
+} NetFlow5Record;
+
+#endif /* __NETFLOW_H__ */
