Wireshark-dev: [Wireshark-dev] [PATCH] Improved Netflow prefs.
From: Andrew Feren <acferen@xxxxxxxxx>
Date: Fri, 11 May 2007 13:28:43 -0700 (PDT)
Thanks to Anders Broman for pointing out, PROTO_ITEM_SET_GENERATED(), and an
example of how to configure multiple dissection ports.

Changes in this patch.
1) Added preference field for IPFIX.
2) User may now specify a range of ports for Netflow (and the new IPFIX
pref.)
3) Netflow defaults to dissect UDP on ports 2055 and 9996
4) IPFIX still defaults to 4739, but now you can change it with out
recompiling
5) marked Duration as a generated field.

The only difference listing a port as IPFIX vs. Netflow ports in the prefs.
is that Netflow only dissects UDP and IPFIX dissects UDP, TCP, and SCTP

-Andrew

-Andrew Feren
 acferen@xxxxxxxxx
Index: epan/dissectors/packet-netflow.c
===================================================================
--- epan/dissectors/packet-netflow.c	(revision 21748)
+++ epan/dissectors/packet-netflow.c	(working copy)
@@ -66,15 +66,21 @@
 
 #include <epan/prefs.h>
 
-#define UDP_PORT_NETFLOW	2055
+/* 4739 is IPFIX.
+   2055 and 9996 are common defaults for Netflow
+ */
+#define NETFLOW_UDP_PORTS "2055, 9996"
+#define IPFIX_UDP_PORTS   "4739"
+static dissector_handle_t netflow_handle;
 
-#define UDP_PORT_IPFIX	        4739
 
-static guint global_netflow_udp_port = UDP_PORT_NETFLOW;
-static guint netflow_udp_port = 0;
-static guint global_ipfix_port = UDP_PORT_IPFIX;
-static guint ipfix_port = 0;
+static range_t *global_netflow_ports = NULL;
+static range_t *netflow_ports = NULL;
 
+static range_t *global_ipfix_ports = NULL;
+static range_t *ipfix_ports = NULL;
+
+
 /*
  * pdu identifiers & sizes 
  */
@@ -731,6 +737,8 @@
 
 	timeitem = proto_tree_add_time(pdutree, hf_cflow_timedelta, tvb, 
 				       offset_s, 8, &ts_delta);
+	PROTO_ITEM_SET_GENERATED(timeitem);
+
 	timetree = proto_item_add_subtree(timeitem, ett_flowtime);
 
 	proto_tree_add_time(timetree, hf_cflow_timestart, tvb, offset_s, 4, 
@@ -1350,6 +1358,7 @@
 				timeitem = 
 				  proto_tree_add_time(pdutree, hf_cflow_timedelta, tvb, 
 						      offset_s, 0, &ts_delta);
+				PROTO_ITEM_SET_GENERATED(timeitem);
 				timetree = proto_item_add_subtree(timeitem, ett_flowtime);
 			
 				proto_tree_add_time(timetree, hf_cflow_timestart, tvb,
@@ -2158,6 +2167,37 @@
 }
 
 
+static void netflow_delete_callback(guint32 port)
+{
+    if ( port ) {
+	dissector_delete("udp.port", port, netflow_handle);
+    }
+}
+static void ipfix_delete_callback(guint32 port)
+{
+    if ( port ) {
+	dissector_delete("udp.port", port, netflow_handle);
+	dissector_delete("tcp.port", port, netflow_handle);
+	dissector_delete("sctp.port", port, netflow_handle);
+    }
+}
+
+static void netflow_add_callback(guint32 port)
+{
+    if ( port ) {
+	dissector_add("udp.port", port, netflow_handle);
+    }
+}
+static void ipfix_add_callback(guint32 port)
+{
+    if ( port ) {
+	dissector_add("udp.port", port, netflow_handle);
+	dissector_add("tcp.port", port, netflow_handle);
+	dissector_add("sctp.port", port, netflow_handle);
+    }
+}
+
+
 static void
 netflow_reinit(void)
 {
@@ -2171,8 +2211,24 @@
 	for (i = 0; i < V9TEMPLATE_CACHE_MAX_ENTRIES; i++)
 		g_free(v9_template_cache[i].entries);
 	memset(v9_template_cache, 0, sizeof v9_template_cache);
+
+	if (netflow_ports) {
+	  range_foreach(netflow_ports, netflow_delete_callback);
+	  g_free(netflow_ports);
+	}
+	if (ipfix_ports) {
+	  range_foreach(ipfix_ports, ipfix_delete_callback);
+	  g_free(ipfix_ports);
+	}
+
+	netflow_ports = range_copy(global_netflow_ports);
+	range_foreach(netflow_ports, netflow_add_callback);
+
+	ipfix_ports = range_copy(global_ipfix_ports);
+	range_foreach(netflow_ports, ipfix_add_callback);
 }
 
+
 void
 proto_register_netflow(void)
 {
@@ -2826,10 +2882,28 @@
 	netflow_module = prefs_register_protocol(proto_netflow,
 	    proto_reg_handoff_netflow);
 
-	prefs_register_uint_preference(netflow_module, "udp.port",
-	    "NetFlow UDP Port", "Set the port for NetFlow messages",
-	    10, &global_netflow_udp_port);
+	/* Set default Neflow port(s) */
+	range_convert_str(&global_netflow_ports, NETFLOW_UDP_PORTS,
+			  MAX_UDP_PORT);
+	netflow_ports = range_copy(global_netflow_ports);
 
+	range_convert_str(&global_ipfix_ports, IPFIX_UDP_PORTS,
+			  MAX_UDP_PORT);
+	ipfix_ports = range_copy(global_ipfix_ports);
+
+
+	prefs_register_range_preference(netflow_module, "netflow.ports",
+					"NetFlow UDP Port(s)", 
+					"Set the port(s) for NetFlow messages",
+					&global_netflow_ports, MAX_UDP_PORT);
+
+	g_assert (MAX_UDP_PORT <= MAX_TCP_PORT);
+	g_assert (MAX_UDP_PORT <= MAX_SCTP_PORT);
+	prefs_register_range_preference(netflow_module, "ipfix.ports",
+					"IPFIX UDP/TCP/SCTP Port(s)", 
+					"Set the port(s) for IPFIX messages",
+					&global_ipfix_ports, MAX_UDP_PORT);
+
 	register_init_routine(&netflow_reinit);
 }
 
@@ -2841,27 +2915,26 @@
 proto_reg_handoff_netflow(void)
 {
 	static int netflow_prefs_initialized = FALSE;
-	static dissector_handle_t netflow_handle;
 
 	if (!netflow_prefs_initialized) {
 		netflow_handle = create_dissector_handle(dissect_netflow,
 		    proto_netflow);
 		netflow_prefs_initialized = TRUE;
 	} else {
-		dissector_delete("udp.port", netflow_udp_port, netflow_handle);
-		dissector_delete("udp.port", ipfix_port,  netflow_handle);
-		dissector_delete("tcp.port", ipfix_port,  netflow_handle);
-		dissector_delete("sctp.port", ipfix_port, netflow_handle);
+		if (netflow_ports) {
+			range_foreach(netflow_ports, netflow_delete_callback);
+			g_free(netflow_ports);
+		}
+		if (ipfix_ports) {
+			range_foreach(ipfix_ports, ipfix_delete_callback);
+			g_free(ipfix_ports);
+		}
 	}
 
-	/* Set out port number for future use */
-	netflow_udp_port = global_netflow_udp_port;
+	netflow_ports = range_copy(global_netflow_ports);
+	range_foreach(netflow_ports, netflow_add_callback);
 
-	dissector_add("udp.port", netflow_udp_port, netflow_handle);
-
-	ipfix_port = global_ipfix_port;
-	dissector_add("udp.port", ipfix_port,  netflow_handle);
-	dissector_add("tcp.port", ipfix_port,  netflow_handle);
-	dissector_add("sctp.port", ipfix_port, netflow_handle);
+	ipfix_ports = range_copy(global_ipfix_ports);
+	range_foreach(ipfix_ports, ipfix_add_callback);
 }