Add support for process flow records to IPFIX, which required adding

support for vendor-specific IEs. Fix variable-length record handling. Add
conversation tracking to the UDP dissector and add process flow
information to TCP and UDP conversations.

This lets us run process flow collectors on one or more machines and
have the process username, PID, command name, etc. show up in the TCP
and UDP protocol trees.

svn path=/trunk/; revision=28366
This commit is contained in:
Gerald Combs 2009-05-14 23:33:17 +00:00
parent bec2875b2b
commit 9a72434b1e
6 changed files with 696 additions and 49 deletions

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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[];