diff options
-rw-r--r-- | epan/dissectors/packet-netflow.c | 330 | ||||
-rw-r--r-- | epan/dissectors/packet-tcp.c | 121 | ||||
-rw-r--r-- | epan/dissectors/packet-tcp.h | 40 | ||||
-rw-r--r-- | epan/dissectors/packet-udp.c | 204 | ||||
-rw-r--r-- | epan/dissectors/packet-udp.h | 47 | ||||
-rw-r--r-- | epan/sminmpec.h | 3 |
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[]; |