aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-netflow.c330
-rw-r--r--epan/dissectors/packet-tcp.c121
-rw-r--r--epan/dissectors/packet-tcp.h40
-rw-r--r--epan/dissectors/packet-udp.c204
-rw-r--r--epan/dissectors/packet-udp.h47
-rw-r--r--epan/sminmpec.h3
6 files changed, 696 insertions, 49 deletions
diff --git a/epan/dissectors/packet-netflow.c b/epan/dissectors/packet-netflow.c
index 2f00264aa9..8149fb6af8 100644
--- a/epan/dissectors/packet-netflow.c
+++ b/epan/dissectors/packet-netflow.c
@@ -71,6 +71,8 @@
#include <epan/prefs.h>
#include <epan/sminmpec.h>
+#include <epan/dissectors/packet-tcp.h>
+#include <epan/dissectors/packet-udp.h>
/* 4739 is IPFIX.
2055 and 9996 are common defaults for Netflow
@@ -111,6 +113,8 @@ static range_t *global_ipfix_ports = NULL;
#define V8PDU_TOSMATRIX_SIZE V8PDU_MATRIX_SIZE
#define V8PDU_PREPORTPROTOCOL_SIZE (4 * 10)
+#define VARIABLE_LENGTH 65535
+
static const value_string v5_sampling_mode[] = {
{0, "No sampling mode configured"},
{1, "Packet Interval sampling mode configured"},
@@ -170,7 +174,7 @@ struct v9_template {
address source_addr;
guint16 option_template; /* 0=data template, 1=option template */
guint16 count_scopes;
- struct v9_template_entry *scopes;
+ struct v9_template_entry *scopes;
struct v9_template_entry *entries;
};
@@ -421,6 +425,21 @@ static int hf_cflow_total_tcp_urg = -1;
static int hf_cflow_ip_total_length64 = -1;
static int hf_cflow_biflow_direction = -1;
+static int hf_pie_cace_local_ipv4_address = -1;
+static int hf_pie_cace_remote_ipv4_address = -1;
+static int hf_pie_cace_local_ipv6_address = -1;
+static int hf_pie_cace_remote_ipv6_address = -1;
+static int hf_pie_cace_local_port = -1;
+static int hf_pie_cace_remote_port = -1;
+static int hf_pie_cace_local_ipv4_id = -1;
+static int hf_pie_cace_local_icmp_id = -1;
+static int hf_pie_cace_local_uid = -1;
+static int hf_pie_cace_local_pid = -1;
+static int hf_pie_cace_local_username_len = -1;
+static int hf_pie_cace_local_username = -1;
+static int hf_pie_cace_local_cmd_len = -1;
+static int hf_pie_cace_local_cmd = -1;
+
const value_string special_mpls_top_label_type[] = {
{0, "Unknown"},
{1, "TE-MIDPT"},
@@ -457,20 +476,20 @@ typedef struct _hdrinfo_t {
address net_src;
} hdrinfo_t;
-typedef int dissect_pdu_t(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+typedef int dissect_pdu_t(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, int offset,
hdrinfo_t * hdrinfo);
-static int dissect_pdu(proto_tree * tree, tvbuff_t * tvb, int offset,
+static int dissect_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, int offset,
hdrinfo_t * hdrinfo);
-static int dissect_v8_aggpdu(proto_tree * pdutree, tvbuff_t * tvb,
+static int dissect_v8_aggpdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree,
int offset, hdrinfo_t * hdrinfo);
-static int dissect_v8_flowpdu(proto_tree * pdutree, tvbuff_t * tvb,
+static int dissect_v8_flowpdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree,
int offset, hdrinfo_t * hdrinfo);
-static int dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb,
+static int dissect_v9_flowset(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree,
int offset, hdrinfo_t * hdrinfo);
-static int dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb,
+static int dissect_v9_data(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree,
int offset, guint16 id, guint length, hdrinfo_t * hdrinfo);
-static void dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb,
+static guint dissect_v9_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree,
int offset, struct v9_template * template);
static int dissect_v9_options(proto_tree * pdutree, tvbuff_t * tvb,
int offset, hdrinfo_t * hdrinfo);
@@ -768,7 +787,7 @@ dissect_netflow(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
pdutree = proto_item_add_subtree(pduitem, ett_flow);
- pduret = pduptr(pdutree, tvb, offset, &hdrinfo);
+ pduret = pduptr(tvb, pinfo, pdutree, offset, &hdrinfo);
if (pduret < pdusize) pduret = pdusize; /* padding */
@@ -891,7 +910,7 @@ flow_process_textfield(proto_tree * pdutree, tvbuff_t * tvb, int offset,
}
static int
-dissect_v8_flowpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+dissect_v8_flowpdu(tvbuff_t * tvb _U_, packet_info * pinfo _U_, proto_tree * pdutree, int offset,
hdrinfo_t * hdrinfo)
{
int startoffset = offset;
@@ -957,7 +976,7 @@ dissect_v8_flowpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
*/
static int
-dissect_v8_aggpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+dissect_v8_aggpdu(tvbuff_t * tvb _U_, packet_info * pinfo _U_, proto_tree * pdutree, int offset,
hdrinfo_t * hdrinfo)
{
int startoffset = offset;
@@ -1106,7 +1125,7 @@ dissect_v8_aggpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
/* Dissect a version 9 FlowSet and return the length we processed. */
static int
-dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb, int offset, hdrinfo_t * hdrinfo)
+dissect_v9_flowset(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree, int offset, hdrinfo_t * hdrinfo)
{
int length;
guint16 flowset_id;
@@ -1169,7 +1188,7 @@ dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb, int offset, hdrinfo_t *
*/
length -= 4;
if (length > 0) {
- dissect_v9_data(pdutree, tvb, offset, flowset_id,
+ dissect_v9_data(tvb, pinfo, pdutree, offset, flowset_id,
(guint)length, hdrinfo);
}
}
@@ -1178,12 +1197,13 @@ dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb, int offset, hdrinfo_t *
}
static int
-dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+dissect_v9_data(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree, int offset,
guint16 id, guint length, hdrinfo_t * hdrinfo)
{
struct v9_template *template;
proto_tree *data_tree;
proto_item *data_item;
+ guint pdu_len;
template = v9_template_get(id, &hdrinfo->net_src, hdrinfo->src_id);
if (template != NULL && template->length != 0) {
@@ -1195,10 +1215,11 @@ dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb, int offset,
data_tree = proto_item_add_subtree(data_item,
ett_dataflowset);
- dissect_v9_pdu(data_tree, tvb, offset, template);
+ pdu_len = dissect_v9_pdu(tvb, pinfo, data_tree, offset, template);
offset += template->length;
- length -= template->length;
+ /* XXX - Throw an exception */
+ length -= pdu_len < length ? pdu_len : length;
}
if (length != 0) {
proto_tree_add_text(pdutree, tvb, offset, length,
@@ -1214,11 +1235,35 @@ dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb, int offset,
return (0);
}
-static void
-dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+#define GOT_LOCAL_ADDR (1 << 0)
+#define GOT_REMOTE_ADDR (1 << 1)
+#define GOT_LOCAL_PORT (1 << 2)
+#define GOT_REMOTE_PORT (1 << 3)
+#define GOT_IPv4_ID (1 << 4)
+#define GOT_ICMP_ID (1 << 5)
+#define GOT_UID (1 << 6)
+#define GOT_PID (1 << 7)
+#define GOT_USERNAME (1 << 8)
+#define GOT_COMMAND (1 << 9)
+
+#define GOT_BASE ( \
+ GOT_LOCAL_ADDR | \
+ GOT_REMOTE_ADDR | \
+ GOT_UID | \
+ GOT_PID | \
+ GOT_USERNAME | \
+ GOT_COMMAND \
+ )
+
+#define GOT_TCP_UDP (GOT_BASE | GOT_LOCAL_PORT | GOT_REMOTE_PORT)
+#define GOT_ICMP (GOT_BASE | GOT_IPv4_ID | GOT_ICMP_ID)
+
+static guint
+dissect_v9_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pdutree, int offset,
struct v9_template * template)
{
- int i;
+ int orig_offset = offset;
+ int i;
int rev;
nstime_t ts_start[2], ts_end[2];
int offset_s[2], offset_e[2];
@@ -1228,6 +1273,14 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
proto_tree * timetree = 0;
proto_item * timeitem = 0;
guint16 pen_count = 0;
+ address local_addr, remote_addr;
+ guint16 local_port = 0, remote_port = 0, ipv4_id = 0, icmp_id = 0;
+ guint32 uid = 0, pid = 0;
+ int uname_len;
+ gchar * uname_str = NULL;
+ int cmd_len;
+ gchar * cmd_str = NULL;
+ guint16 got_flags = 0;
offset_s[0] = offset_s[1] = offset_e[0] = offset_e[1] = 0;
msec_start[0] = msec_start[1] = msec_end[0] = msec_end[1] = 0;
@@ -1279,6 +1332,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
}
for (i = 0; i < template->count; i++) {
+ guint64 pen_type;
guint16 type, length;
guint32 pen = 0;
@@ -1294,7 +1348,9 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
}
}
- switch (type) {
+ pen_type = pen << 16 | (type & 0x7fff);
+
+ switch (pen_type) {
case 85: /* BYTES_PERMANENT */
case 1: /* bytes */
@@ -1627,7 +1683,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
if (length == 4) {
proto_tree_add_item(pdutree, hf_cflow_ipv6_flowlabel,
tvb, offset, length, FALSE);
- }
+ }
/* RFC3954 defines that length of this field is 3
Bytes */
else if (length == 3) {
@@ -1835,7 +1891,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
proto_tree_add_item(pdutree, hf_cflow_ipv6_exthdr,
tvb, offset, length, FALSE);
break;
-
+
case 70: /* MPLS label1*/
proto_tree_add_mpls_label(pdutree, tvb, offset, length, 1);
break;
@@ -1905,7 +1961,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
proto_tree_add_item(pdutree, hf_cflow_fragment_offset,
tvb, offset, length, FALSE);
break;
-
+
case 89: /* FORWARDING_STATUS */
proto_tree_add_item(pdutree, hf_cflow_forwarding_status,
tvb, offset, length, FALSE);
@@ -1938,7 +1994,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
hf_cflow_exporter_addr_v6,
tvb, offset, length, FALSE);
break;
-
+
case 132: /* droppedOctetDeltaCount */
if (length == 4) {
proto_tree_add_item(pdutree, hf_cflow_drop_octets,
@@ -2007,7 +2063,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
proto_tree_add_item(pdutree, hf_cflow_observation_point_id,
tvb, offset, length, FALSE);
break;
-
+
case 139: /* icmpTypeCodeIPv6 */
proto_tree_add_item(pdutree, hf_cflow_icmp_ipv6_type,
tvb, offset, 1, FALSE);
@@ -2041,7 +2097,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
proto_tree_add_item(pdutree, hf_cflow_mp_id,
tvb, offset, length, FALSE);
break;
-
+
case 144: /* FLOW EXPORTER */
proto_tree_add_item(pdutree, hf_cflow_flow_exporter,
tvb, offset, length, FALSE);
@@ -2162,7 +2218,7 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
"Not Sent Packets: length %u", length);
}
break;
-
+
case 169: /* destinationIPv6Prefix */
if (length == 16) {
proto_tree_add_item(pdutree, hf_cflow_dstnet_v6,
@@ -2499,12 +2555,105 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
tvb, offset, length, FALSE);
break;
+ /* CACE Technologies */
+ case VENDOR_CACE << 16 | 0: /* caceLocalIPv4Address */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_ipv4_address,
+ tvb, offset, length, FALSE);
+ SET_ADDRESS(&local_addr, AT_IPv4, 4, tvb_get_ptr(tvb, offset, 4));
+ got_flags |= GOT_LOCAL_ADDR;
+ break;
+
+ case VENDOR_CACE << 16 | 1: /* caceRemoteIPv4Address */
+ proto_tree_add_item(pdutree, hf_pie_cace_remote_ipv4_address,
+ tvb, offset, length, FALSE);
+ SET_ADDRESS(&remote_addr, AT_IPv4, 4, tvb_get_ptr(tvb, offset, 4));
+ got_flags |= GOT_REMOTE_ADDR;
+ break;
+
+ case VENDOR_CACE << 16 | 2: /* caceLocalIPv6Address */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_ipv6_address,
+ tvb, offset, length, FALSE);
+ SET_ADDRESS(&local_addr, AT_IPv6, 16, tvb_get_ptr(tvb, offset, 16));
+ got_flags |= GOT_LOCAL_ADDR;
+ break;
+
+ case VENDOR_CACE << 16 | 3: /* caceRemoteIPv6Address */
+ proto_tree_add_item(pdutree, hf_pie_cace_remote_ipv6_address,
+ tvb, offset, length, FALSE);
+ SET_ADDRESS(&remote_addr, AT_IPv6, 16, tvb_get_ptr(tvb, offset, 16));
+ got_flags |= GOT_REMOTE_ADDR;
+ break;
+
+ case VENDOR_CACE << 16 | 4: /* caceLocalTransportPort */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_port,
+ tvb, offset, length, FALSE);
+ local_port = tvb_get_ntohs(tvb, offset);
+ got_flags |= GOT_LOCAL_PORT;
+ break;
+
+ case VENDOR_CACE << 16 | 5: /* caceRemoteTransportPort */
+ proto_tree_add_item(pdutree, hf_pie_cace_remote_port,
+ tvb, offset, length, FALSE);
+ remote_port = tvb_get_ntohs(tvb, offset);
+ got_flags |= GOT_REMOTE_PORT;
+ break;
+
+ case VENDOR_CACE << 16 | 6: /* caceLocalIPv4id */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_ipv4_id,
+ tvb, offset, length, FALSE);
+ ipv4_id = tvb_get_ntohs(tvb, offset);
+ got_flags |= GOT_IPv4_ID;
+ break;
+
+ case VENDOR_CACE << 16 | 7: /* caceLocalICMPid */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_icmp_id,
+ tvb, offset, length, FALSE);
+ icmp_id = tvb_get_ntohs(tvb, offset);
+ got_flags |= GOT_ICMP_ID;
+ break;
+
+ case VENDOR_CACE << 16 | 8: /* caceLocalProcessUserId */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_uid,
+ tvb, offset, length, FALSE);
+ uid = tvb_get_ntohl(tvb, offset);
+ got_flags |= GOT_UID;
+ break;
+
+ case VENDOR_CACE << 16 | 9: /* caceLocalProcessId */
+ proto_tree_add_item(pdutree, hf_pie_cace_local_pid,
+ tvb, offset, length, FALSE);
+ pid = tvb_get_ntohl(tvb, offset);
+ got_flags |= GOT_PID;
+ break;
+
+ case VENDOR_CACE << 16 | 10: /* caceLocalProcessUserName */
+ uname_len = tvb_get_guint8(tvb, offset);
+ uname_str = tvb_format_text(tvb, offset+1, uname_len);
+ proto_tree_add_item(pdutree, hf_pie_cace_local_username_len,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_string(pdutree, hf_pie_cace_local_username,
+ tvb, offset+1, uname_len, uname_str);
+ length = uname_len + 1;
+ got_flags |= GOT_USERNAME;
+ break;
+
+ case VENDOR_CACE << 16 | 11: /* caceLocalProcessCommand */
+ cmd_len = tvb_get_guint8(tvb, offset);
+ cmd_str = tvb_format_text(tvb, offset+1, cmd_len);
+ proto_tree_add_item(pdutree, hf_pie_cace_local_cmd_len,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_string(pdutree, hf_pie_cace_local_cmd,
+ tvb, offset+1, cmd_len, cmd_str);
+ length = cmd_len + 1;
+ got_flags |= GOT_COMMAND;
+ break;
+
default:
if ((type & 0x8000) && (pen != REVPEN))
proto_tree_add_text(pdutree, tvb, offset, length,
"(%s) Type %u ",
match_strval(pen, sminmpec_values), type & 0x7fff);
-
+
else
proto_tree_add_text(pdutree, tvb, offset, length,
"%s Type %u %s", pen == REVPEN ? "Reverse" : "",
@@ -2537,6 +2686,16 @@ dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
}
}
+ /* XXX - These IDs are currently hard-coded in procflow.py. */
+ if (got_flags == GOT_TCP_UDP && (template->id == 256 || template->id == 258)) {
+ add_tcp_process_info(pinfo->fd->num, &local_addr, &remote_addr, local_port, remote_port, uid, pid, uname_str, cmd_str);
+ }
+ if (got_flags == GOT_TCP_UDP && (template->id == 257 || template->id == 259)) {
+ add_udp_process_info(pinfo->fd->num, &local_addr, &remote_addr, local_port, remote_port, uid, pid, uname_str, cmd_str);
+ }
+
+ return (guint) (offset - orig_offset);
+
}
static int
@@ -2710,7 +2869,7 @@ dissect_v9_template(proto_tree * pdutree, tvbuff_t * tvb, int offset, int len, h
v9_template_add(&template);
remaining -= 4 + sizeof(struct v9_template_entry) * count;
if (pen_count > 0) {
- remaining -= 4 * pen_count;
+ remaining -= 4 * pen_count;
}
}
@@ -2983,22 +3142,25 @@ v9_template_add(struct v9_template *template)
{
int i;
int pen_count = 0;
+ guint tmp_length;
/* Add up the actual length of the data and store in proper byte order */
template->length = 0;
/* Options scope */
for(i = 0; i < template->count_scopes; i++) {
template->scopes[i].type = g_ntohs(template->scopes[i].type);
- template->scopes[i].length = g_ntohs(template->scopes[i].length);
+ tmp_length = g_ntohs(template->scopes[i].length);
+ template->scopes[i].length = tmp_length == VARIABLE_LENGTH ? 0 : tmp_length;
template->length += template->scopes[i].length;
}
for (i = 0; i < template->count; i++) {
template->entries[i + pen_count].type = g_ntohs(template->entries[i + pen_count].type);
- template->entries[i + pen_count].length = g_ntohs(template->entries[i + pen_count].length);
+ tmp_length = g_ntohs(template->entries[i + pen_count].length);
+ template->entries[i + pen_count].length = tmp_length == VARIABLE_LENGTH ? 0 : tmp_length;
template->length += template->entries[i + pen_count].length;
if (template->entries[i + pen_count].type & 0x8000) {
pen_count++;
- *(guint32 *)&template->entries[i + pen_count] =
+ *(guint32 *)&template->entries[i + pen_count] =
g_ntohl(*(guint32 *)&template->entries[i + pen_count]);
}
}
@@ -3030,7 +3192,7 @@ v9_template_get(guint16 id, address * net_src, guint32 src_id)
*/
static int
-dissect_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset, hdrinfo_t * hdrinfo)
+dissect_pdu(tvbuff_t * tvb, packet_info * pinfo _U_, proto_tree * pdutree, int offset, hdrinfo_t * hdrinfo)
{
proto_item *hidden_item;
int startoffset = offset;
@@ -4238,7 +4400,95 @@ proto_register_netflow(void)
{"Scope Unknown", "cflow.scope",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Option Scope Unknown", HFILL}
- }
+ },
+
+ /* Private Information Elements */
+
+ /* CACE Technologies, 32622 / 0 */
+ {&hf_pie_cace_local_ipv4_address,
+ {"Local IPv4 Address", "cflow.pie.cace.localaddr4",
+ FT_IPv4, BASE_HEX, NULL, 0x0,
+ "Local IPv4 Address (caceLocalIPv4Address)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 1 */
+ {&hf_pie_cace_remote_ipv4_address,
+ {"Remote IPv4 Address", "cflow.pie.cace.remoteaddr4",
+ FT_IPv4, BASE_HEX, NULL, 0x0,
+ "Remote IPv4 Address (caceRemoteIPv4Address)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 2 */
+ {&hf_pie_cace_local_ipv6_address,
+ {"Local IPv6 Address", "cflow.pie.cace.localaddr6",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "Local IPv6 Address (caceLocalIPv6Address)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 3 */
+ {&hf_pie_cace_remote_ipv6_address,
+ {"Remote IPv6 Address", "cflow.pie.cace.remoteaddr6",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "Remote IPv6 Address (caceRemoteIPv6Address)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 4 */
+ {&hf_pie_cace_local_port,
+ {"Local Port", "cflow.pie.cace.localport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Local Transport Port (caceLocalTransportPort)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 5 */
+ {&hf_pie_cace_remote_port,
+ {"Remote Port", "cflow.pie.cace.remoteport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Remote Transport Port (caceRemoteTransportPort)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 6 */
+ {&hf_pie_cace_local_ipv4_id,
+ {"Local IPv4 ID", "cflow.pie.cace.localip4id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The IPv4 identification header field from a locally-originated packet (caceLocalIPv4id)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 7 */
+ {&hf_pie_cace_local_icmp_id,
+ {"Local ICMP ID", "cflow.pie.cace.localicmpid",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The ICMP identification header field from a locally-originated ICMPv4 or ICMPv6 echo request (caceLocalICMPid)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 8 */
+ {&hf_pie_cace_local_uid,
+ {"Local User ID", "cflow.pie.cace.localuid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Local User ID (caceLocalProcessUserId)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 9 */
+ {&hf_pie_cace_local_pid,
+ {"Local Process ID", "cflow.pie.cace.localpid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Local Process ID (caceLocalProcessId)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 10 */
+ {&hf_pie_cace_local_username_len,
+ {"Local Username Length", "cflow.pie.cace.localusernamelen",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Local User Name Length (caceLocalProcessUserName)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 10 */
+ {&hf_pie_cace_local_username,
+ {"Local User Name", "cflow.pie.cace.localusername",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Local User Name (caceLocalProcessUserName)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 11 */
+ {&hf_pie_cace_local_cmd_len,
+ {"Local Command Length", "cflow.pie.cace.localcmdlen",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Local Command Length (caceLocalProcessCommand)", HFILL}
+ },
+ /* CACE Technologies, 32622 / 11 */
+ {&hf_pie_cace_local_cmd,
+ {"Local Command", "cflow.pie.cace.localcmd",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Local Command (caceLocalProcessCommand)", HFILL}
+ }
+
};
static gint *ett[] = {
@@ -4350,3 +4600,15 @@ proto_reg_handoff_netflow(void)
range_foreach(ipfix_ports, ipfix_add_callback);
}
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set shiftwidth=8 tabstop=8 noexpandtab
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index ad73e8797f..a34ed243e9 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -159,6 +159,14 @@ static int hf_tcp_option_snack_offset = -1;
static int hf_tcp_option_snack_size = -1;
static int hf_tcp_option_snack_le = -1;
static int hf_tcp_option_snack_re = -1;
+static int hf_tcp_proc_src_uid = -1;
+static int hf_tcp_proc_src_pid = -1;
+static int hf_tcp_proc_src_uname = -1;
+static int hf_tcp_proc_src_cmd = -1;
+static int hf_tcp_proc_dst_uid = -1;
+static int hf_tcp_proc_dst_pid = -1;
+static int hf_tcp_proc_dst_uname = -1;
+static int hf_tcp_proc_dst_cmd = -1;
static gint ett_tcp = -1;
static gint ett_tcp_flags = -1;
@@ -172,6 +180,7 @@ static gint ett_tcp_timestamps = -1;
static gint ett_tcp_segments = -1;
static gint ett_tcp_segment = -1;
static gint ett_tcp_checksum = -1;
+static gint ett_tcp_process_info = -1;
/* not all of the hf_fields below make sense for TCP but we have to provide
@@ -250,8 +259,12 @@ init_tcp_conversation_data(packet_info *pinfo)
memset(&tcpd->flow2, 0, sizeof(tcp_flow_t));
tcpd->flow1.win_scale=-1;
tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
+ tcpd->flow1.username = NULL;
+ tcpd->flow1.command = NULL;
tcpd->flow2.win_scale=-1;
tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
+ tcpd->flow2.username = NULL;
+ tcpd->flow2.command = NULL;
tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
@@ -319,6 +332,40 @@ get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
return tcpd;
}
+/* Attach process info to a flow */
+/* XXX - We depend on the TCP dissector finding the conversation first */
+void
+add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) {
+ conversation_t *conv;
+ struct tcp_analysis *tcpd;
+ tcp_flow_t *flow = NULL;
+
+ conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
+ if (!conv) {
+ return;
+ }
+
+ tcpd = conversation_get_proto_data(conv, proto_tcp);
+ if (!tcpd) {
+ return;
+ }
+
+ if (CMP_ADDRESS(local_addr, &conv->key_ptr->addr1) == 0 && local_port == conv->key_ptr->port1) {
+ flow = &tcpd->flow1;
+ } else if (CMP_ADDRESS(remote_addr, &conv->key_ptr->addr1) == 0 && remote_port == conv->key_ptr->port1) {
+ flow = &tcpd->flow2;
+ }
+ if (!flow || flow->command) {
+ return;
+ }
+
+ flow->process_uid = uid;
+ flow->process_pid = pid;
+ flow->username = se_strdup(username);
+ flow->command = se_strdup(command);
+}
+
+
/* Calculate the timestamps relative to this conversation */
static void
tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
@@ -3553,6 +3600,32 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
+ if (tcpd && (tcpd->fwd || tcpd->rev) && (tcpd->fwd->command || tcpd->rev->command)) {
+ ti = proto_tree_add_text(tcp_tree, tvb, offset, 0, "Process Information");
+ PROTO_ITEM_SET_GENERATED(ti);
+ field_tree = proto_item_add_subtree(ti, ett_tcp_process_info);
+ if (tcpd->fwd->command) {
+ proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0,
+ tcpd->fwd->process_uid, "%u", tcpd->fwd->process_uid);
+ proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0,
+ tcpd->fwd->process_pid, "%u", tcpd->fwd->process_pid);
+ proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0,
+ tcpd->fwd->username, "%s", tcpd->fwd->username);
+ proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0,
+ tcpd->fwd->command, "%s", tcpd->fwd->command);
+ }
+ if (tcpd->rev->command) {
+ proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0,
+ tcpd->rev->process_uid, "%u", tcpd->rev->process_uid);
+ proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0,
+ tcpd->rev->process_pid, "%u", tcpd->rev->process_pid);
+ proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0,
+ tcpd->rev->username, "%s", tcpd->rev->username);
+ proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0,
+ tcpd->rev->command, "%s", tcpd->rev->command);
+ }
+ }
+
/*
* XXX - what, if any, of this should we do if this is included in an
* error packet? It might be nice to see the details of the packet
@@ -3983,6 +4056,38 @@ proto_register_tcp(void)
{ &hf_tcp_ts_delta,
{ "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
"Time delta from previous frame in this TCP stream", HFILL}},
+
+ { &hf_tcp_proc_src_uid,
+ { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Source process user ID", HFILL}},
+
+ { &hf_tcp_proc_src_pid,
+ { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Source process ID", HFILL}},
+
+ { &hf_tcp_proc_src_uname,
+ { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Source process user name", HFILL}},
+
+ { &hf_tcp_proc_src_cmd,
+ { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Source process command name", HFILL}},
+
+ { &hf_tcp_proc_dst_uid,
+ { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Destination process user ID", HFILL}},
+
+ { &hf_tcp_proc_dst_pid,
+ { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Destination process ID", HFILL}},
+
+ { &hf_tcp_proc_dst_uname,
+ { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Destination process user name", HFILL}},
+
+ { &hf_tcp_proc_dst_cmd,
+ { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Destination process command name", HFILL}}
};
static gint *ett[] = {
@@ -3997,7 +4102,8 @@ proto_register_tcp(void)
&ett_tcp_timestamps,
&ett_tcp_segments,
&ett_tcp_segment,
- &ett_tcp_checksum
+ &ett_tcp_checksum,
+ &ett_tcp_process_info
};
module_t *tcp_module;
@@ -4063,3 +4169,16 @@ proto_reg_handoff_tcp(void)
data_handle = find_dissector("data");
tcp_tap = register_tap("tcp");
}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=4 noexpandtab
+ * :indentSize=4:tabSize=4:noTabs=false:
+ */
diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h
index a261fb0ec3..e3e7bcbdef 100644
--- a/epan/dissectors/packet-tcp.h
+++ b/epan/dissectors/packet-tcp.h
@@ -61,7 +61,7 @@ struct tcpheader {
};
/*
- * Private data passed from the TCP dissector to subdissectors. Passed to the
+ * Private data passed from the TCP dissector to subdissectors. Passed to the
* subdissectors in pinfo->private_data
*/
struct tcpinfo {
@@ -111,9 +111,9 @@ typedef struct _tcp_unacked_t {
struct tcp_acked {
guint32 frame_acked;
nstime_t ts;
-
- guint32 rto_frame;
- nstime_t rto_ts; /* Time since previous packet for
+
+ guint32 rto_frame;
+ nstime_t rto_ts; /* Time since previous packet for
retransmissions. */
guint16 flags;
guint32 dupack_num; /* dup ack number */
@@ -140,16 +140,16 @@ typedef struct _tcp_flow_t {
*/
tcp_unacked_t *segments;
guint32 lastack; /* last seen ack */
- nstime_t lastacktime; /* Time of the last ack packet */
+ nstime_t lastacktime; /* Time of the last ack packet */
guint32 lastnondupack; /* frame number of last seen non dupack */
guint32 dupacknum; /* dupack number */
guint32 nextseq; /* highest seen nextseq */
guint32 nextseqframe; /* frame number for segment with highest
* sequence number
*/
- nstime_t nextseqtime; /* Time of the nextseq packet so we can
- * distinguish between retransmission,
- * fast retransmissions and outoforder
+ nstime_t nextseqtime; /* Time of the nextseq packet so we can
+ * distinguish between retransmission,
+ * fast retransmissions and outoforder
*/
guint32 window; /* last seen window */
gint16 win_scale; /* -1 is we dont know */
@@ -167,8 +167,14 @@ typedef struct _tcp_flow_t {
* all pdus spanning multiple segments for this flow.
*/
emem_tree_t *multisegment_pdus;
+
+ /* Process info, currently discovered via IPFIX */
+ guint32 process_uid; /* UID of local process */
+ guint32 process_pid; /* PID of local process */
+ gchar *username; /* Username of the local process */
+ gchar *command; /* Local process name + path + args */
} tcp_flow_t;
-
+
struct tcp_analysis {
/* These two structs are managed based on comparing the source
@@ -196,7 +202,7 @@ struct tcp_analysis {
/* This pointer is NULL or points to a tcp_acked struct if this
* packet has "interesting" properties such as being a KeepAlive or
- * similar
+ * similar
*/
struct tcp_acked *ta;
/* This structure contains a tree containing all the various ta's
@@ -232,10 +238,22 @@ extern void dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset,
proto_tree *tcp_tree,
struct tcp_analysis *tcpd);
-extern struct tcp_analysis *get_tcp_conversation_data(conversation_t *conv,
+extern struct tcp_analysis *get_tcp_conversation_data(conversation_t *conv,
packet_info *pinfo);
extern gboolean decode_tcp_ports(tvbuff_t *, int, packet_info *, proto_tree *, int, int, struct tcp_analysis *);
+/** Associate process information with a given flow
+ *
+ * @param local_addr The local IPv4 or IPv6 address of the process
+ * @param remote_addr The remote IPv4 or IPv6 address of the process
+ * @param local_port The local TCP port of the process
+ * @param remote_port The remote TCP port of the process
+ * @param uid The numeric user ID of the process
+ * @param pid The numeric PID of the process
+ * @param username Ephemeral string containing the full or partial process name
+ * @param command Ephemeral string containing the full or partial process name
+ */
+extern void add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command);
#endif
diff --git a/epan/dissectors/packet-udp.c b/epan/dissectors/packet-udp.c
index 0a0f2d5fc2..6e35f58701 100644
--- a/epan/dissectors/packet-udp.c
+++ b/epan/dissectors/packet-udp.c
@@ -62,9 +62,18 @@ static int hf_udplite_checksum_coverage_bad = -1;
static int hf_udp_checksum = -1;
static int hf_udp_checksum_good = -1;
static int hf_udp_checksum_bad = -1;
+static int hf_udp_proc_src_uid = -1;
+static int hf_udp_proc_src_pid = -1;
+static int hf_udp_proc_src_uname = -1;
+static int hf_udp_proc_src_cmd = -1;
+static int hf_udp_proc_dst_uid = -1;
+static int hf_udp_proc_dst_pid = -1;
+static int hf_udp_proc_dst_uname = -1;
+static int hf_udp_proc_dst_cmd = -1;
static gint ett_udp = -1;
static gint ett_udp_checksum = -1;
+static gint ett_udp_process_info = -1;
/* Preferences */
@@ -74,6 +83,9 @@ static gboolean udp_summary_in_tree = TRUE;
/* Check UDP checksums */
static gboolean udp_check_checksum = FALSE;
+/* Collect IPFIX process flow information */
+static gboolean udp_process_info = FALSE;
+
/* Ignore an invalid checksum coverage field for UDPLite */
static gboolean udplite_ignore_checksum_coverage = TRUE;
@@ -90,6 +102,121 @@ static dissector_handle_t data_handle;
static gboolean try_heuristic_first = FALSE;
+
+/* Conversation and process code originally copied from packet-tcp.c */
+static struct udp_analysis *
+init_udp_conversation_data(packet_info *pinfo)
+{
+ struct udp_analysis *udpd=NULL;
+
+ /* Initialize the udp protocol data structure to add to the udp conversation */
+ udpd = se_alloc0(sizeof(struct udp_analysis));
+ memset(&udpd->flow1, 0, sizeof(udp_flow_t));
+ memset(&udpd->flow2, 0, sizeof(udp_flow_t));
+ udpd->flow1.username = NULL;
+ udpd->flow1.command = NULL;
+ udpd->flow2.username = NULL;
+ udpd->flow2.command = NULL;
+
+ return udpd;
+}
+
+static conversation_t *
+get_udp_conversation(packet_info *pinfo)
+{
+ conversation_t *conv=NULL;
+
+ /* Have we seen this conversation before? */
+ if( (conv=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0)) == NULL){
+ /* No this is a new conversation. */
+ conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ return conv;
+}
+
+static struct udp_analysis *
+get_udp_conversation_data(conversation_t *conv, packet_info *pinfo)
+{
+ int direction;
+ struct udp_analysis *udpd=NULL;
+
+ /* Did the caller supply the conversation pointer? */
+ if( conv==NULL )
+ conv = get_udp_conversation(pinfo);
+
+ /* Get the data for this conversation */
+ udpd=conversation_get_proto_data(conv, proto_udp);
+
+ /* If the conversation was just created or it matched a
+ * conversation with template options, udpd will not
+ * have been initialized. So, initialize
+ * a new udpd structure for the conversation.
+ */
+ if (!udpd) {
+ udpd = init_udp_conversation_data(pinfo);
+ conversation_add_proto_data(conv, proto_udp, udpd);
+ }
+
+ if (!udpd) {
+ return NULL;
+ }
+
+ /* check direction and get ua lists */
+ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ /* if the addresses are equal, match the ports instead */
+ if(direction==0) {
+ direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
+ }
+ if(direction>=0){
+ udpd->fwd=&(udpd->flow1);
+ udpd->rev=&(udpd->flow2);
+ } else {
+ udpd->fwd=&(udpd->flow2);
+ udpd->rev=&(udpd->flow1);
+ }
+
+ return udpd;
+}
+
+/* Attach process info to a flow */
+/* XXX - We depend on the UDP dissector finding the conversation first */
+void
+add_udp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) {
+ conversation_t *conv;
+ struct udp_analysis *udpd;
+ udp_flow_t *flow = NULL;
+
+ if (!udp_process_info) {
+ return;
+ }
+
+ conv = find_conversation(frame_num, local_addr, remote_addr, PT_UDP, local_port, remote_port, 0);
+ if (!conv) {
+ return;
+ }
+
+ udpd = conversation_get_proto_data(conv, proto_udp);
+ if (!udpd) {
+ return;
+ }
+
+ if (CMP_ADDRESS(local_addr, &conv->key_ptr->addr1) == 0 && local_port == conv->key_ptr->port1) {
+ flow = &udpd->flow1;
+ } else if (CMP_ADDRESS(remote_addr, &conv->key_ptr->addr1) == 0 && remote_port == conv->key_ptr->port1) {
+ flow = &udpd->flow2;
+ }
+ if (!flow || flow->command) {
+ return;
+ }
+
+ flow->process_uid = uid;
+ flow->process_pid = pid;
+ flow->username = se_strdup(username);
+ flow->command = se_strdup(command);
+}
+
+
+
void
decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
@@ -187,6 +314,9 @@ dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
e_udphdr *udph;
proto_tree *checksum_tree;
proto_item *item;
+ conversation_t *conv = NULL;
+ struct udp_analysis *udpd = NULL;
+ proto_tree *process_tree;
udph=ep_alloc(sizeof(e_udphdr));
SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
@@ -417,6 +547,39 @@ dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
pinfo->destport = udph->uh_dport;
tap_queue_packet(udp_tap, pinfo, udph);
+
+ /* find(or create if needed) the conversation for this udp session */
+ if (udp_process_info) {
+ conv=get_udp_conversation(pinfo);
+ udpd=get_udp_conversation_data(conv,pinfo);
+ }
+
+ if (udpd && (udpd->fwd || udpd->rev) && (udpd->fwd->command || udpd->rev->command)) {
+ ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information");
+ PROTO_ITEM_SET_GENERATED(ti);
+ process_tree = proto_item_add_subtree(ti, ett_udp_process_info);
+ if (udpd->fwd->command) {
+ proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0,
+ udpd->fwd->process_uid, "%u", udpd->fwd->process_uid);
+ proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0,
+ udpd->fwd->process_pid, "%u", udpd->fwd->process_pid);
+ proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0,
+ udpd->fwd->username, "%s", udpd->fwd->username);
+ proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0,
+ udpd->fwd->command, "%s", udpd->fwd->command);
+ }
+ if (udpd->rev->command) {
+ proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0,
+ udpd->rev->process_uid, "%u", udpd->rev->process_uid);
+ proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0,
+ udpd->rev->process_pid, "%u", udpd->rev->process_pid);
+ proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0,
+ udpd->rev->username, "%s", udpd->rev->username);
+ proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0,
+ udpd->rev->command, "%s", udpd->rev->command);
+ }
+ }
+
/*
* Call sub-dissectors.
*
@@ -479,7 +642,39 @@ proto_register_udp(void)
{ &hf_udp_checksum_bad,
{ "Bad Checksum", "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }}
+ "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
+
+ { &hf_udp_proc_src_uid,
+ { "Source process user ID", "udp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Source process user ID", HFILL}},
+
+ { &hf_udp_proc_src_pid,
+ { "Source process ID", "udp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Source process ID", HFILL}},
+
+ { &hf_udp_proc_src_uname,
+ { "Source process user name", "udp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Source process user name", HFILL}},
+
+ { &hf_udp_proc_src_cmd,
+ { "Source process name", "udp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Source process command name", HFILL}},
+
+ { &hf_udp_proc_dst_uid,
+ { "Destination process user ID", "udp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Destination process user ID", HFILL}},
+
+ { &hf_udp_proc_dst_pid,
+ { "Destination process ID", "udp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Destination process ID", HFILL}},
+
+ { &hf_udp_proc_dst_uname,
+ { "Destination process user name", "udp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Destination process user name", HFILL}},
+
+ { &hf_udp_proc_dst_cmd,
+ { "Destination process name", "udp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Destination process command name", HFILL}}
};
static hf_register_info hf_lite[] = {
@@ -494,7 +689,8 @@ proto_register_udp(void)
static gint *ett[] = {
&ett_udp,
- &ett_udp_checksum
+ &ett_udp_checksum,
+ &ett_udp_process_info
};
proto_udp = proto_register_protocol("User Datagram Protocol",
@@ -526,6 +722,10 @@ proto_register_udp(void)
"Validate the UDP checksum if possible",
"Whether to validate the UDP checksum",
&udp_check_checksum);
+ prefs_register_bool_preference(udp_module, "process_info",
+ "Collect process flow information",
+ "Collect process flow information from IPFIX",
+ &udp_process_info);
udplite_module = prefs_register_protocol(proto_udplite, NULL);
prefs_register_bool_preference(udplite_module, "ignore_checksum_coverage",
diff --git a/epan/dissectors/packet-udp.h b/epan/dissectors/packet-udp.h
index 4cb043b7f3..c289b241a2 100644
--- a/epan/dissectors/packet-udp.h
+++ b/epan/dissectors/packet-udp.h
@@ -36,6 +36,53 @@ typedef struct _e_udphdr {
address ip_dst;
} e_udphdr;
+/* Conversation and process structures originally copied from packet-tcp.c */
+typedef struct _udp_flow_t {
+ /* Process info, currently discovered via IPFIX */
+ guint32 process_uid; /* UID of local process */
+ guint32 process_pid; /* PID of local process */
+ gchar *username; /* Username of the local process */
+ gchar *command; /* Local process name + path + args */
+} udp_flow_t;
+
+struct udp_analysis {
+ /* These two structs are managed based on comparing the source
+ * and destination addresses and, if they're equal, comparing
+ * the source and destination ports.
+ *
+ * If the source is greater than the destination, then stuff
+ * sent from src is in ual1.
+ *
+ * If the source is less than the destination, then stuff
+ * sent from src is in ual2.
+ *
+ * XXX - if the addresses and ports are equal, we don't guarantee
+ * the behavior.
+ */
+ udp_flow_t flow1;
+ udp_flow_t flow2;
+
+ /* These pointers are set by get_tcp_conversation_data()
+ * fwd point in the same direction as the current packet
+ * and rev in the reverse direction
+ */
+ udp_flow_t *fwd;
+ udp_flow_t *rev;
+};
+
+/** Associate process information with a given flow
+ *
+ * @param local_addr The local IPv4 or IPv6 address of the process
+ * @param remote_addr The remote IPv4 or IPv6 address of the process
+ * @param local_port The local TCP port of the process
+ * @param remote_port The remote TCP port of the process
+ * @param uid The numeric user ID of the process
+ * @param pid The numeric PID of the process
+ * @param username Ephemeral string containing the full or partial process name
+ * @param command Ephemeral string containing the full or partial process name
+ */
+extern void add_udp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command);
+
extern void decode_udp_ports(tvbuff_t *, int, packet_info *,
proto_tree *, int, int, int);
diff --git a/epan/sminmpec.h b/epan/sminmpec.h
index 0ae64f97a3..6ba20936fb 100644
--- a/epan/sminmpec.h
+++ b/epan/sminmpec.h
@@ -75,7 +75,8 @@
#define VENDOR_THE3GPP 10415
#define VENDOR_GEMTEK_SYSTEMS 10529
#define VENDOR_WIFI_ALLIANCE 14122
-#define VENDOR_T_SYSTEMS_NOVA 16787
+#define VENDOR_T_SYSTEMS_NOVA 16787
+#define VENDOR_CACE 32622
WS_VAR_IMPORT const value_string sminmpec_values[];