b982023107
Use a better pattern than formatting the string for display multiple times. Code is cleaner avoids wasteful calls to format_text() that can be slightly expensive. In some cases it might not have exactly the same whitespace semantics for the column info (escape vs replace) but that's OK.
1695 lines
55 KiB
C
1695 lines
55 KiB
C
/* packet-rpcap.c
|
|
*
|
|
* Routines for RPCAP message formats.
|
|
*
|
|
* Copyright 2008, Stig Bjorlykke <stig@bjorlykke.org>, Thales Norway AS
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/aftypes.h>
|
|
#include <epan/prefs.h>
|
|
#include <epan/to_str.h>
|
|
#include <epan/expert.h>
|
|
#include <epan/exceptions.h>
|
|
#include <epan/show_exception.h>
|
|
#include <wsutil/str_util.h>
|
|
|
|
#include "packet-frame.h"
|
|
#include "packet-pcap_pktdata.h"
|
|
#include "packet-tcp.h"
|
|
|
|
#define PNAME "Remote Packet Capture"
|
|
#define PSNAME "RPCAP"
|
|
#define PFNAME "rpcap"
|
|
|
|
#define RPCAP_MSG_ERROR 0x01
|
|
#define RPCAP_MSG_FINDALLIF_REQ 0x02
|
|
#define RPCAP_MSG_OPEN_REQ 0x03
|
|
#define RPCAP_MSG_STARTCAP_REQ 0x04
|
|
#define RPCAP_MSG_UPDATEFILTER_REQ 0x05
|
|
#define RPCAP_MSG_CLOSE 0x06
|
|
#define RPCAP_MSG_PACKET 0x07
|
|
#define RPCAP_MSG_AUTH_REQ 0x08
|
|
#define RPCAP_MSG_STATS_REQ 0x09
|
|
#define RPCAP_MSG_ENDCAP_REQ 0x0A
|
|
#define RPCAP_MSG_SETSAMPLING_REQ 0x0B
|
|
|
|
#define RPCAP_MSG_FINDALLIF_REPLY (0x80+RPCAP_MSG_FINDALLIF_REQ)
|
|
#define RPCAP_MSG_OPEN_REPLY (0x80+RPCAP_MSG_OPEN_REQ)
|
|
#define RPCAP_MSG_STARTCAP_REPLY (0x80+RPCAP_MSG_STARTCAP_REQ)
|
|
#define RPCAP_MSG_UPDATEFILTER_REPLY (0x80+RPCAP_MSG_UPDATEFILTER_REQ)
|
|
#define RPCAP_MSG_AUTH_REPLY (0x80+RPCAP_MSG_AUTH_REQ)
|
|
#define RPCAP_MSG_STATS_REPLY (0x80+RPCAP_MSG_STATS_REQ)
|
|
#define RPCAP_MSG_ENDCAP_REPLY (0x80+RPCAP_MSG_ENDCAP_REQ)
|
|
#define RPCAP_MSG_SETSAMPLING_REPLY (0x80+RPCAP_MSG_SETSAMPLING_REQ)
|
|
|
|
#define RPCAP_ERR_NETW 1
|
|
#define RPCAP_ERR_INITTIMEOUT 2
|
|
#define RPCAP_ERR_AUTH 3
|
|
#define RPCAP_ERR_FINDALLIF 4
|
|
#define RPCAP_ERR_NOREMOTEIF 5
|
|
#define RPCAP_ERR_OPEN 6
|
|
#define RPCAP_ERR_UPDATEFILTER 7
|
|
#define RPCAP_ERR_GETSTATS 8
|
|
#define RPCAP_ERR_READEX 9
|
|
#define RPCAP_ERR_HOSTNOAUTH 10
|
|
#define RPCAP_ERR_REMOTEACCEPT 11
|
|
#define RPCAP_ERR_STARTCAPTURE 12
|
|
#define RPCAP_ERR_ENDCAPTURE 13
|
|
#define RPCAP_ERR_RUNTIMETIMEOUT 14
|
|
#define RPCAP_ERR_SETSAMPLING 15
|
|
#define RPCAP_ERR_WRONGMSG 16
|
|
#define RPCAP_ERR_WRONGVER 17
|
|
|
|
#define RPCAP_SAMP_NOSAMP 0
|
|
#define RPCAP_SAMP_1_EVERY_N 1
|
|
#define RPCAP_SAMP_FIRST_AFTER_N_MS 2
|
|
|
|
#define RPCAP_RMTAUTH_NULL 0
|
|
#define RPCAP_RMTAUTH_PWD 1
|
|
|
|
#define FLAG_PROMISC 0x0001
|
|
#define FLAG_DGRAM 0x0002
|
|
#define FLAG_SERVEROPEN 0x0004
|
|
#define FLAG_INBOUND 0x0008
|
|
#define FLAG_OUTBOUND 0x0010
|
|
|
|
void proto_register_rpcap (void);
|
|
void proto_reg_handoff_rpcap (void);
|
|
|
|
static int proto_rpcap = -1;
|
|
|
|
static int hf_version = -1;
|
|
static int hf_type = -1;
|
|
static int hf_value = -1;
|
|
static int hf_plen = -1;
|
|
|
|
static int hf_error = -1;
|
|
static int hf_error_value = -1;
|
|
|
|
static int hf_packet = -1;
|
|
static int hf_timestamp = -1;
|
|
static int hf_caplen = -1;
|
|
static int hf_len = -1;
|
|
static int hf_npkt = -1;
|
|
|
|
static int hf_auth_request = -1;
|
|
static int hf_auth_type = -1;
|
|
static int hf_auth_slen1 = -1;
|
|
static int hf_auth_slen2 = -1;
|
|
static int hf_auth_username = -1;
|
|
static int hf_auth_password = -1;
|
|
|
|
static int hf_auth_reply = -1;
|
|
static int hf_auth_minvers = -1;
|
|
static int hf_auth_maxvers = -1;
|
|
|
|
static int hf_open_request = -1;
|
|
|
|
static int hf_open_reply = -1;
|
|
static int hf_linktype = -1;
|
|
static int hf_tzoff = -1;
|
|
|
|
static int hf_startcap_request = -1;
|
|
static int hf_snaplen = -1;
|
|
static int hf_read_timeout = -1;
|
|
static int hf_flags = -1;
|
|
static int hf_flags_promisc = -1;
|
|
static int hf_flags_dgram = -1;
|
|
static int hf_flags_serveropen = -1;
|
|
static int hf_flags_inbound = -1;
|
|
static int hf_flags_outbound = -1;
|
|
static int hf_client_port = -1;
|
|
static int hf_startcap_reply = -1;
|
|
static int hf_bufsize = -1;
|
|
static int hf_server_port = -1;
|
|
static int hf_dummy = -1;
|
|
|
|
static int hf_filter = -1;
|
|
static int hf_filtertype = -1;
|
|
static int hf_nitems = -1;
|
|
|
|
static int hf_filterbpf_insn = -1;
|
|
static int hf_code = -1;
|
|
static int hf_code_class = -1;
|
|
static int hf_code_fields = -1;
|
|
static int hf_code_ld_size = -1;
|
|
static int hf_code_ld_mode = -1;
|
|
static int hf_code_alu_op = -1;
|
|
static int hf_code_jmp_op = -1;
|
|
static int hf_code_src = -1;
|
|
static int hf_code_rval = -1;
|
|
static int hf_code_misc_op = -1;
|
|
static int hf_jt = -1;
|
|
static int hf_jf = -1;
|
|
static int hf_instr_value = -1;
|
|
|
|
static int hf_stats_reply = -1;
|
|
static int hf_ifrecv = -1;
|
|
static int hf_ifdrop = -1;
|
|
static int hf_krnldrop = -1;
|
|
static int hf_srvcapt = -1;
|
|
|
|
static int hf_findalldevs_reply = -1;
|
|
static int hf_findalldevs_if = -1;
|
|
static int hf_namelen = -1;
|
|
static int hf_desclen = -1;
|
|
static int hf_if_flags = -1;
|
|
static int hf_naddr = -1;
|
|
static int hf_if_name = -1;
|
|
static int hf_if_desc = -1;
|
|
|
|
static int hf_findalldevs_ifaddr = -1;
|
|
static int hf_if_addr = -1;
|
|
static int hf_if_netmask = -1;
|
|
static int hf_if_broadaddr = -1;
|
|
static int hf_if_dstaddr = -1;
|
|
static int hf_if_af = -1;
|
|
static int hf_if_port = -1;
|
|
static int hf_if_ipv4 = -1;
|
|
static int hf_if_flowinfo = -1;
|
|
static int hf_if_ipv6 = -1;
|
|
static int hf_if_scopeid = -1;
|
|
static int hf_if_padding = -1;
|
|
static int hf_if_unknown = -1;
|
|
|
|
static int hf_sampling_request = -1;
|
|
static int hf_sampling_method = -1;
|
|
static int hf_sampling_dummy1 = -1;
|
|
static int hf_sampling_dummy2 = -1;
|
|
static int hf_sampling_value = -1;
|
|
|
|
static gint ett_rpcap = -1;
|
|
static gint ett_error = -1;
|
|
static gint ett_packet = -1;
|
|
static gint ett_auth_request = -1;
|
|
static gint ett_auth_reply = -1;
|
|
static gint ett_open_reply = -1;
|
|
static gint ett_startcap_request = -1;
|
|
static gint ett_startcap_reply = -1;
|
|
static gint ett_startcap_flags = -1;
|
|
static gint ett_filter = -1;
|
|
static gint ett_filterbpf_insn = -1;
|
|
static gint ett_filterbpf_insn_code = -1;
|
|
static gint ett_stats_reply = -1;
|
|
static gint ett_findalldevs_reply = -1;
|
|
static gint ett_findalldevs_if = -1;
|
|
static gint ett_findalldevs_ifaddr = -1;
|
|
static gint ett_ifaddr = -1;
|
|
static gint ett_sampling_request = -1;
|
|
|
|
static expert_field ei_error = EI_INIT;
|
|
static expert_field ei_if_unknown = EI_INIT;
|
|
static expert_field ei_no_more_data = EI_INIT;
|
|
static expert_field ei_caplen_too_big = EI_INIT;
|
|
|
|
static dissector_handle_t pcap_pktdata_handle;
|
|
static dissector_handle_t rpcap_tcp_handle;
|
|
|
|
/* User definable values */
|
|
static gboolean rpcap_desegment = TRUE;
|
|
static gboolean decode_content = TRUE;
|
|
static int global_linktype = -1;
|
|
|
|
/* Global variables */
|
|
static int linktype = -1;
|
|
static gboolean info_added = FALSE;
|
|
|
|
static const value_string message_type[] = {
|
|
{ RPCAP_MSG_ERROR, "Error" },
|
|
{ RPCAP_MSG_FINDALLIF_REQ, "Find all interfaces request" },
|
|
{ RPCAP_MSG_OPEN_REQ, "Open request" },
|
|
{ RPCAP_MSG_STARTCAP_REQ, "Start capture request" },
|
|
{ RPCAP_MSG_UPDATEFILTER_REQ, "Update filter request" },
|
|
{ RPCAP_MSG_CLOSE, "Close" },
|
|
{ RPCAP_MSG_PACKET, "Packet" },
|
|
{ RPCAP_MSG_AUTH_REQ, "Authentication request" },
|
|
{ RPCAP_MSG_STATS_REQ, "Statistics request" },
|
|
{ RPCAP_MSG_ENDCAP_REQ, "End capture request" },
|
|
{ RPCAP_MSG_SETSAMPLING_REQ, "Set sampling request" },
|
|
{ RPCAP_MSG_FINDALLIF_REPLY, "Find all interfaces reply" },
|
|
{ RPCAP_MSG_OPEN_REPLY, "Open reply" },
|
|
{ RPCAP_MSG_STARTCAP_REPLY, "Start capture reply" },
|
|
{ RPCAP_MSG_UPDATEFILTER_REPLY, "Update filter reply" },
|
|
{ RPCAP_MSG_AUTH_REPLY, "Authentication reply" },
|
|
{ RPCAP_MSG_STATS_REPLY, "Statistics reply" },
|
|
{ RPCAP_MSG_ENDCAP_REPLY, "End capture reply" },
|
|
{ RPCAP_MSG_SETSAMPLING_REPLY, "Set sampling reply" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string error_codes[] = {
|
|
{ RPCAP_ERR_NETW, "Network error" },
|
|
{ RPCAP_ERR_INITTIMEOUT, "Initial timeout has expired" },
|
|
{ RPCAP_ERR_AUTH, "Authentication error" },
|
|
{ RPCAP_ERR_FINDALLIF, "Generic findalldevs error" },
|
|
{ RPCAP_ERR_NOREMOTEIF, "No remote interfaces" },
|
|
{ RPCAP_ERR_OPEN, "Generic pcap_open error" },
|
|
{ RPCAP_ERR_UPDATEFILTER, "Generic updatefilter error" },
|
|
{ RPCAP_ERR_GETSTATS, "Generic pcap_stats error" },
|
|
{ RPCAP_ERR_READEX, "Generic pcap_next_ex error" },
|
|
{ RPCAP_ERR_HOSTNOAUTH, "The host is not authorized" },
|
|
{ RPCAP_ERR_REMOTEACCEPT, "Generic pcap_remoteaccept error" },
|
|
{ RPCAP_ERR_STARTCAPTURE, "Generic pcap_startcapture error" },
|
|
{ RPCAP_ERR_ENDCAPTURE, "Generic pcap_endcapture error" },
|
|
{ RPCAP_ERR_RUNTIMETIMEOUT, "Runtime timeout has expired" },
|
|
{ RPCAP_ERR_SETSAMPLING, "Error in setting sampling parameters" },
|
|
{ RPCAP_ERR_WRONGMSG, "Unrecognized message" },
|
|
{ RPCAP_ERR_WRONGVER, "Incompatible version" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string sampling_method[] = {
|
|
{ RPCAP_SAMP_NOSAMP, "No sampling" },
|
|
{ RPCAP_SAMP_1_EVERY_N, "1 every N" },
|
|
{ RPCAP_SAMP_FIRST_AFTER_N_MS, "First after N ms" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string auth_type[] = {
|
|
{ RPCAP_RMTAUTH_NULL, "None" },
|
|
{ RPCAP_RMTAUTH_PWD, "Password" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_class[] = {
|
|
{ 0x00, "ld" },
|
|
{ 0x01, "ldx" },
|
|
{ 0x02, "st" },
|
|
{ 0x03, "stx" },
|
|
{ 0x04, "alu" },
|
|
{ 0x05, "jmp" },
|
|
{ 0x06, "ret" },
|
|
{ 0x07, "misc" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_size[] = {
|
|
{ 0x00, "w" },
|
|
{ 0x01, "h" },
|
|
{ 0x02, "b" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_mode[] = {
|
|
{ 0x00, "imm" },
|
|
{ 0x01, "abs" },
|
|
{ 0x02, "ind" },
|
|
{ 0x03, "mem" },
|
|
{ 0x04, "len" },
|
|
{ 0x05, "msh" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_alu_op[] = {
|
|
{ 0x00, "add" },
|
|
{ 0x01, "sub" },
|
|
{ 0x02, "mul" },
|
|
{ 0x03, "div" },
|
|
{ 0x04, "or" },
|
|
{ 0x05, "and" },
|
|
{ 0x06, "lsh" },
|
|
{ 0x07, "rsh" },
|
|
{ 0x08, "neg" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_jmp_op[] = {
|
|
{ 0x00, "ja" },
|
|
{ 0x01, "jeq" },
|
|
{ 0x02, "jgt" },
|
|
{ 0x03, "jge" },
|
|
{ 0x04, "jset" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_src[] = {
|
|
{ 0x00, "k" },
|
|
{ 0x01, "x" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_rval[] = {
|
|
{ 0x00, "k" },
|
|
{ 0x01, "x" },
|
|
{ 0x02, "a" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string bpf_misc_op[] = {
|
|
{ 0x00, "tax" },
|
|
{ 0x10, "txa" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
static void rpcap_frame_end (void)
|
|
{
|
|
info_added = FALSE;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_error (tvbuff_t *tvb, packet_info *pinfo,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_item *ti;
|
|
gint len;
|
|
char *str;
|
|
|
|
len = tvb_reported_length_remaining (tvb, offset);
|
|
if (len <= 0)
|
|
return;
|
|
|
|
ti = proto_tree_add_item_ret_display_string(parent_tree, hf_error, tvb, offset, len, ENC_ASCII, pinfo->pool, &str);
|
|
expert_add_info_format(pinfo, ti, &ei_error, "Error: %s", str);
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", str);
|
|
}
|
|
|
|
/*
|
|
* There's some painful history with this part of a findalldevs reply.
|
|
*
|
|
* Older RPCAPDs sent the addresses over the wire in the OS's native
|
|
* structure format. For most OSes, this looks like the over-the-wire
|
|
* format, but might have a different value for AF_INET6 than the value
|
|
* on the machine receiving the reply. For OSes with the newer BSD-style
|
|
* sockaddr structures, this has, instead of a 2-byte address family,
|
|
* a 1-byte structure length followed by a 1-byte address family. The
|
|
* RPCAPD code would put the address family in network byte order before
|
|
* sending it; that would set it to 0 on a little-endian machine, as
|
|
* htons() of any value between 1 and 255 would result in a value > 255,
|
|
* with its lower 8 bits zero, so putting that back into a 1-byte field
|
|
* would set it to 0.
|
|
*
|
|
* Therefore, for older RPCAPDs running on an OS with newer BSD-style
|
|
* sockaddr structures, the family field, if treated as a big-endian
|
|
* (network byte order) 16-bit field, would be:
|
|
*
|
|
* (length << 8) | family if sent by a big-endian machine
|
|
* (length << 8) if sent by a little-endian machine
|
|
*
|
|
* For current RPCAPDs, and for older RPCAPDs running on an OS with
|
|
* older BSD-style sockaddr structures, the family field, if treated
|
|
* as a big-endian 16-bit field, would just contain the family.
|
|
*
|
|
* (An additional bit of pain was that the structure was sent over the
|
|
* wire as a network-byte-order struct sockaddr_storage, which does
|
|
* *not* have the same size on all platforms. On most platforms, the
|
|
* structure is 128 bytes long; on Solaris, however, it's 256 bytes
|
|
* long. Neither the rpcap client code in libpcap, nor we, try to
|
|
* detect Solaris addresses and deal with them.)
|
|
*
|
|
* The current rpcapd serializes the socket addresses as 128-byte
|
|
* structures, containing:
|
|
*
|
|
* a 2-octet address family value, in network byte order;
|
|
*
|
|
* a 4-octet IPv4 address, if the address family value is 2
|
|
* (the AF_INET value on all supported platforms);
|
|
*
|
|
* a 16-octet IPv6 address, if the address family value is
|
|
* 23 (the Windows AF_INET6 value, chosen because Windows
|
|
* was, before rpcap was changed to standardize the format,
|
|
* the only platform for which precompiled binaries for
|
|
* rpcapd were generally available);
|
|
*
|
|
* padding up to 128 bytes.
|
|
*
|
|
* The rpcap client code, and we, check for those address family values,
|
|
* as well as other values that might have been produced by the old
|
|
* code on various platforms.
|
|
*/
|
|
|
|
/*
|
|
* Possible IPv4 family values other than the designated over-the-wire value,
|
|
* which is 2 (because everybody uses 2 for AF_INET4).
|
|
*/
|
|
#define SOCKADDR_IN_LEN 16 /* length of struct sockaddr_in */
|
|
#define NEW_BSD_AF_INET_BE ((SOCKADDR_IN_LEN << 8) | BSD_AF_INET)
|
|
#define NEW_BSD_AF_INET_LE (SOCKADDR_IN_LEN << 8)
|
|
|
|
/*
|
|
* Possible IPv6 family values other than the designated over-the-wire value,
|
|
* which is 23 (because that's what Windows uses, and most RPCAP servers
|
|
* out there are probably running Windows, as WinPcap includes the server
|
|
* but few if any UN*Xes build and ship it). Some are defined in
|
|
* <epan/aftypes.h>.
|
|
*
|
|
* The new BSD sockaddr structure format was in place before 4.4-Lite, so
|
|
* all the free-software BSDs use it.
|
|
*/
|
|
#define SOCKADDR_IN6_LEN 28 /* length of struct sockaddr_in6 */
|
|
#define NEW_BSD_AF_INET6_BSD_BE ((SOCKADDR_IN6_LEN << 8) | BSD_AF_INET6_BSD) /* NetBSD, OpenBSD, BSD/OS */
|
|
#define NEW_BSD_AF_INET6_FREEBSD_BE ((SOCKADDR_IN6_LEN << 8) | BSD_AF_INET6_FREEBSD) /* FreeBSD, DragonFly BSD */
|
|
#define NEW_BSD_AF_INET6_DARWIN_BE ((SOCKADDR_IN6_LEN << 8) | BSD_AF_INET6_DARWIN) /* macOS, iOS, anything else Darwin-based */
|
|
#define NEW_BSD_AF_INET6_LE (SOCKADDR_IN6_LEN << 8)
|
|
#define HPUX_AF_INET6 22
|
|
#define AIX_AF_INET6 24
|
|
|
|
static const value_string address_family[] = {
|
|
{ COMMON_AF_UNSPEC, "AF_UNSPEC" },
|
|
{ COMMON_AF_INET, "AF_INET" },
|
|
{ NEW_BSD_AF_INET_BE, "AF_INET (old server code on big-endian 4.4-Lite-based OS)" },
|
|
{ NEW_BSD_AF_INET_LE, "AF_INET (old server code on little-endian 4.4-Lite-based OS)" },
|
|
{ WINSOCK_AF_INET6, "AF_INET6" },
|
|
{ NEW_BSD_AF_INET6_BSD_BE, "AF_INET6 (old server code on big-endian NetBSD, OpenBSD, BSD/OS)" },
|
|
{ NEW_BSD_AF_INET6_FREEBSD_BE, "AF_INET6 (old server code on big-endian FreeBSD)" },
|
|
{ NEW_BSD_AF_INET6_DARWIN_BE, "AF_INET6 (old server code on big-endian Mac OS X)" },
|
|
{ NEW_BSD_AF_INET6_LE, "AF_INET6 (old server code on little-endian 4.4-Lite-based OS)" },
|
|
{ LINUX_AF_INET6, "AF_INET6 (old server code on Linux)" },
|
|
{ HPUX_AF_INET6, "AF_INET6 (old server code on HP-UX)" },
|
|
{ AIX_AF_INET6, "AF_INET6 (old server code on AIX)" },
|
|
{ SOLARIS_AF_INET6, "AF_INET6 (old server code on Solaris)" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static gint
|
|
dissect_rpcap_ifaddr (tvbuff_t *tvb, packet_info *pinfo,
|
|
proto_tree *parent_tree, gint offset, int hf_id,
|
|
proto_item *parent_item)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint16 af;
|
|
guint32 ipv4;
|
|
ws_in6_addr ipv6;
|
|
gchar ipaddr[MAX_ADDR_STR_LEN];
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_id, tvb, offset, 128, ENC_BIG_ENDIAN);
|
|
tree = proto_item_add_subtree (ti, ett_ifaddr);
|
|
|
|
af = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_if_af, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
switch (af) {
|
|
|
|
case COMMON_AF_INET:
|
|
case NEW_BSD_AF_INET_BE:
|
|
case NEW_BSD_AF_INET_LE:
|
|
proto_tree_add_item (tree, hf_if_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
ipv4 = tvb_get_ipv4 (tvb, offset);
|
|
ip_to_str_buf((guint8 *)&ipv4, ipaddr, MAX_ADDR_STR_LEN);
|
|
proto_item_append_text (ti, ": %s", ipaddr);
|
|
if (parent_item) {
|
|
proto_item_append_text (parent_item, ": %s", ipaddr);
|
|
}
|
|
proto_tree_add_item (tree, hf_if_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_if_padding, tvb, offset, 120, ENC_NA);
|
|
offset += 120;
|
|
break;
|
|
|
|
case WINSOCK_AF_INET6:
|
|
case NEW_BSD_AF_INET6_BSD_BE:
|
|
case NEW_BSD_AF_INET6_FREEBSD_BE:
|
|
case NEW_BSD_AF_INET6_DARWIN_BE:
|
|
case NEW_BSD_AF_INET6_LE:
|
|
case LINUX_AF_INET6:
|
|
case HPUX_AF_INET6:
|
|
case AIX_AF_INET6:
|
|
case SOLARIS_AF_INET6:
|
|
proto_tree_add_item (tree, hf_if_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_if_flowinfo, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
tvb_get_ipv6 (tvb, offset, &ipv6);
|
|
ip6_to_str_buf(&ipv6, ipaddr, MAX_ADDR_STR_LEN);
|
|
proto_item_append_text (ti, ": %s", ipaddr);
|
|
if (parent_item) {
|
|
proto_item_append_text (parent_item, ": %s", ipaddr);
|
|
}
|
|
proto_tree_add_item (tree, hf_if_ipv6, tvb, offset, 16, ENC_NA);
|
|
offset += 16;
|
|
|
|
proto_tree_add_item (tree, hf_if_scopeid, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_if_padding, tvb, offset, 108, ENC_NA);
|
|
offset += 100;
|
|
break;
|
|
|
|
default:
|
|
ti = proto_tree_add_item (tree, hf_if_unknown, tvb, offset, 126, ENC_NA);
|
|
if (af != COMMON_AF_UNSPEC) {
|
|
expert_add_info_format(pinfo, ti, &ei_if_unknown,
|
|
"Unknown address family: %d", af);
|
|
}
|
|
offset += 126;
|
|
break;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static gint
|
|
dissect_rpcap_findalldevs_ifaddr (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
gint boffset = offset;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_findalldevs_ifaddr, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_findalldevs_ifaddr);
|
|
|
|
offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_addr, ti);
|
|
offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_netmask, NULL);
|
|
offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_broadaddr, NULL);
|
|
offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_dstaddr, NULL);
|
|
|
|
proto_item_set_len (ti, offset - boffset);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static gint
|
|
dissect_rpcap_findalldevs_if (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint16 namelen, desclen, naddr, i;
|
|
gint boffset = offset;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_findalldevs_if, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_findalldevs_if);
|
|
|
|
namelen = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_namelen, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
desclen = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_desclen, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_if_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
naddr = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_naddr, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
if (namelen) {
|
|
const guint8* name;
|
|
proto_tree_add_item_ret_string(tree, hf_if_name, tvb, offset, namelen, ENC_ASCII|ENC_NA, pinfo->pool, &name);
|
|
proto_item_append_text (ti, ": %s", name);
|
|
offset += namelen;
|
|
}
|
|
|
|
if (desclen) {
|
|
proto_tree_add_item (tree, hf_if_desc, tvb, offset, desclen, ENC_ASCII);
|
|
offset += desclen;
|
|
}
|
|
|
|
for (i = 0; i < naddr; i++) {
|
|
offset = dissect_rpcap_findalldevs_ifaddr (tvb, pinfo, tree, offset);
|
|
if (tvb_reported_length_remaining (tvb, offset) < 0) {
|
|
/* No more data in packet */
|
|
expert_add_info(pinfo, ti, &ei_no_more_data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
proto_item_set_len (ti, offset - boffset);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_findalldevs_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset, guint16 no_devs)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint16 i;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_findalldevs_reply, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_findalldevs_reply);
|
|
|
|
for (i = 0; i < no_devs; i++) {
|
|
offset = dissect_rpcap_findalldevs_if (tvb, pinfo, tree, offset);
|
|
if (tvb_reported_length_remaining (tvb, offset) < 0) {
|
|
/* No more data in packet */
|
|
expert_add_info(pinfo, ti, &ei_no_more_data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
proto_item_append_text (ti, ", %d item%s", no_devs, plurality (no_devs, "", "s"));
|
|
}
|
|
|
|
|
|
static gint
|
|
dissect_rpcap_filterbpf_insn (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree, *code_tree;
|
|
proto_item *ti, *code_ti;
|
|
guint8 inst_class;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_filterbpf_insn, tvb, offset, 8, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_filterbpf_insn);
|
|
|
|
code_ti = proto_tree_add_item (tree, hf_code, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
code_tree = proto_item_add_subtree (code_ti, ett_filterbpf_insn_code);
|
|
proto_tree_add_item (code_tree, hf_code_class, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
inst_class = tvb_get_guint8 (tvb, offset + 1) & 0x07;
|
|
proto_item_append_text (ti, ": %s", val_to_str_const (inst_class, bpf_class, ""));
|
|
switch (inst_class) {
|
|
case 0x00: /* ld */
|
|
case 0x01: /* ldx */
|
|
proto_tree_add_item (code_tree, hf_code_ld_size, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (code_tree, hf_code_ld_mode, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
case 0x04: /* alu */
|
|
proto_tree_add_item (code_tree, hf_code_src, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (code_tree, hf_code_alu_op, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
case 0x05: /* jmp */
|
|
proto_tree_add_item (code_tree, hf_code_src, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (code_tree, hf_code_jmp_op, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
case 0x06: /* ret */
|
|
proto_tree_add_item (code_tree, hf_code_rval, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
case 0x07: /* misc */
|
|
proto_tree_add_item (code_tree, hf_code_misc_op, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
default:
|
|
proto_tree_add_item (code_tree, hf_code_fields, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
break;
|
|
}
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_jt, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item (tree, hf_jf, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item (tree, hf_instr_value, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_filter (tvbuff_t *tvb, packet_info *pinfo,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint32 nitems, i;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_filter, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_filter);
|
|
|
|
proto_tree_add_item (tree, hf_filtertype, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
nitems = tvb_get_ntohl (tvb, offset);
|
|
proto_tree_add_item (tree, hf_nitems, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
for (i = 0; i < nitems; i++) {
|
|
offset = dissect_rpcap_filterbpf_insn (tvb, pinfo, tree, offset);
|
|
if (tvb_reported_length_remaining (tvb, offset) < 0) {
|
|
/* No more data in packet */
|
|
expert_add_info(pinfo, ti, &ei_no_more_data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_rpcap_auth_request (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint16 type, slen1, slen2;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_auth_request, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_auth_request);
|
|
|
|
type = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
slen1 = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_auth_slen1, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
slen2 = tvb_get_ntohs (tvb, offset);
|
|
proto_tree_add_item (tree, hf_auth_slen2, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
if (type == RPCAP_RMTAUTH_NULL) {
|
|
proto_item_append_text (ti, " (none)");
|
|
} else if (type == RPCAP_RMTAUTH_PWD) {
|
|
const guint8 *username, *password;
|
|
|
|
proto_tree_add_item_ret_string(tree, hf_auth_username, tvb, offset, slen1, ENC_ASCII|ENC_NA, pinfo->pool, &username);
|
|
offset += slen1;
|
|
|
|
proto_tree_add_item_ret_string(tree, hf_auth_password, tvb, offset, slen2, ENC_ASCII|ENC_NA, pinfo->pool, &password);
|
|
offset += slen2;
|
|
|
|
proto_item_append_text (ti, " (%s/%s)", username, password);
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_auth_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint32 minvers, maxvers;
|
|
|
|
/*
|
|
* Authentication replies from older servers have no payload.
|
|
* Replies from newer servers have a payload.
|
|
* Dissect the payload if we have any.
|
|
*/
|
|
if (tvb_reported_length_remaining(tvb, offset) != 0) {
|
|
ti = proto_tree_add_item (parent_tree, hf_auth_reply, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_auth_reply);
|
|
|
|
proto_tree_add_item_ret_uint (tree, hf_auth_minvers, tvb, offset, 1, ENC_BIG_ENDIAN, &minvers);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item_ret_uint (tree, hf_auth_maxvers, tvb, offset, 1, ENC_BIG_ENDIAN, &maxvers);
|
|
|
|
proto_item_append_text (ti, ", minimum version %u, maximum version %u", minvers, maxvers);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_open_request (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
gint len;
|
|
|
|
len = tvb_reported_length_remaining (tvb, offset);
|
|
proto_tree_add_item (parent_tree, hf_open_request, tvb, offset, len, ENC_ASCII);
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_open_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_open_reply, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_open_reply);
|
|
|
|
linktype = tvb_get_ntohl (tvb, offset);
|
|
proto_tree_add_item (tree, hf_linktype, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_tzoff, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_startcap_request (tvbuff_t *tvb, packet_info *pinfo,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree, *field_tree;
|
|
proto_item *ti, *field_ti;
|
|
guint16 flags;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_startcap_request, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_startcap_request);
|
|
|
|
proto_tree_add_item (tree, hf_snaplen, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_read_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
flags = tvb_get_ntohs (tvb, offset);
|
|
field_ti = proto_tree_add_uint_format (tree, hf_flags, tvb, offset, 2, flags, "Flags");
|
|
field_tree = proto_item_add_subtree (field_ti, ett_startcap_flags);
|
|
proto_tree_add_item (field_tree, hf_flags_promisc, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (field_tree, hf_flags_dgram, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (field_tree, hf_flags_serveropen, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (field_tree, hf_flags_inbound, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item (field_tree, hf_flags_outbound, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
|
|
if (flags & 0x1F) {
|
|
gchar *flagstr = wmem_strdup_printf (pinfo->pool, "%s%s%s%s%s",
|
|
(flags & FLAG_PROMISC) ? ", Promiscuous" : "",
|
|
(flags & FLAG_DGRAM) ? ", Datagram" : "",
|
|
(flags & FLAG_SERVEROPEN) ? ", ServerOpen" : "",
|
|
(flags & FLAG_INBOUND) ? ", Inbound" : "",
|
|
(flags & FLAG_OUTBOUND) ? ", Outbound" : "");
|
|
proto_item_append_text (field_ti, ":%s", &flagstr[1]);
|
|
} else {
|
|
proto_item_append_text (field_ti, " (none)");
|
|
}
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
dissect_rpcap_filter (tvb, pinfo, tree, offset);
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_startcap_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_startcap_reply, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_startcap_reply);
|
|
|
|
proto_tree_add_item (tree, hf_bufsize, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_server_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_stats_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_stats_reply, tvb, offset, 16, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_stats_reply);
|
|
|
|
proto_tree_add_item (tree, hf_ifrecv, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_ifdrop, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_krnldrop, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_tree_add_item (tree, hf_srvcapt, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_rpcap_sampling_request (tvbuff_t *tvb, packet_info *pinfo _U_,
|
|
proto_tree *parent_tree, gint offset)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
guint32 value;
|
|
guint8 method;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_sampling_request, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_sampling_request);
|
|
|
|
method = tvb_get_guint8 (tvb, offset);
|
|
proto_tree_add_item (tree, hf_sampling_method, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item (tree, hf_sampling_dummy1, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item (tree, hf_sampling_dummy2, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
value = tvb_get_ntohl (tvb, offset);
|
|
proto_tree_add_item (tree, hf_sampling_value, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
switch (method) {
|
|
case RPCAP_SAMP_NOSAMP:
|
|
proto_item_append_text (ti, ": None");
|
|
break;
|
|
case RPCAP_SAMP_1_EVERY_N:
|
|
proto_item_append_text (ti, ": 1 every %d", value);
|
|
break;
|
|
case RPCAP_SAMP_FIRST_AFTER_N_MS:
|
|
proto_item_append_text (ti, ": First after %d ms", value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_rpcap_packet (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree,
|
|
proto_tree *parent_tree, gint offset, proto_item *top_item)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
tvbuff_t *new_tvb;
|
|
guint caplen, len, frame_no;
|
|
gint reported_length_remaining;
|
|
|
|
ti = proto_tree_add_item (parent_tree, hf_packet, tvb, offset, 20, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_packet);
|
|
|
|
proto_tree_add_item(tree, hf_timestamp, tvb, offset, 8, ENC_TIME_SECS_USECS|ENC_BIG_ENDIAN);
|
|
offset += 8;
|
|
|
|
caplen = tvb_get_ntohl (tvb, offset);
|
|
ti = proto_tree_add_item (tree, hf_caplen, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
len = tvb_get_ntohl (tvb, offset);
|
|
proto_tree_add_item (tree, hf_len, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
frame_no = tvb_get_ntohl (tvb, offset);
|
|
proto_tree_add_item (tree, hf_npkt, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_item_append_text (ti, ", Frame %u", frame_no);
|
|
proto_item_append_text (top_item, " Frame %u", frame_no);
|
|
|
|
/*
|
|
* reported_length_remaining should not be -1, as offset is at
|
|
* most right past the end of the available data in the packet.
|
|
*/
|
|
reported_length_remaining = tvb_reported_length_remaining (tvb, offset);
|
|
if (caplen > (guint)reported_length_remaining) {
|
|
expert_add_info(pinfo, ti, &ei_caplen_too_big);
|
|
return;
|
|
}
|
|
|
|
new_tvb = tvb_new_subset_length_caplen (tvb, offset, caplen, len);
|
|
if (decode_content && linktype != -1) {
|
|
TRY {
|
|
call_dissector_with_data(pcap_pktdata_handle, new_tvb, pinfo, top_tree, &linktype);
|
|
}
|
|
CATCH_BOUNDS_ERRORS {
|
|
show_exception(tvb, pinfo, top_tree, EXCEPT_CODE, GET_MESSAGE);
|
|
}
|
|
ENDTRY;
|
|
|
|
if (!info_added) {
|
|
/* Only indicate when not added before */
|
|
/* Indicate RPCAP in the protocol column */
|
|
col_prepend_fence_fstr(pinfo->cinfo, COL_PROTOCOL, "R|");
|
|
|
|
/* Indicate RPCAP in the info column */
|
|
col_prepend_fence_fstr (pinfo->cinfo, COL_INFO, "Remote | ");
|
|
info_added = TRUE;
|
|
register_frame_end_routine(pinfo, rpcap_frame_end);
|
|
}
|
|
} else {
|
|
if (linktype == -1) {
|
|
proto_item_append_text (ti, ", Unknown link-layer type");
|
|
}
|
|
call_data_dissector(new_tvb, pinfo, top_tree);
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_rpcap (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree, void* data _U_)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *ti;
|
|
tvbuff_t *new_tvb;
|
|
gint len, offset = 0;
|
|
guint8 msg_type;
|
|
guint16 msg_value;
|
|
|
|
col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME);
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
ti = proto_tree_add_item (top_tree, proto_rpcap, tvb, offset, -1, ENC_NA);
|
|
tree = proto_item_add_subtree (ti, ett_rpcap);
|
|
|
|
proto_tree_add_item (tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset++;
|
|
|
|
msg_type = tvb_get_guint8 (tvb, offset);
|
|
proto_tree_add_item (tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset++;
|
|
|
|
col_append_str (pinfo->cinfo, COL_INFO,
|
|
val_to_str (msg_type, message_type, "Unknown: 0x%02x"));
|
|
|
|
proto_item_append_text (ti, ", %s", val_to_str (msg_type, message_type, "Unknown: 0x%02x"));
|
|
|
|
msg_value = tvb_get_ntohs (tvb, offset);
|
|
if (msg_type == RPCAP_MSG_ERROR) {
|
|
proto_tree_add_item (tree, hf_error_value, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
} else {
|
|
proto_tree_add_item (tree, hf_value, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
offset += 2;
|
|
|
|
proto_tree_add_item (tree, hf_plen, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
|
|
switch (msg_type) {
|
|
case RPCAP_MSG_ERROR:
|
|
dissect_rpcap_error (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_OPEN_REQ:
|
|
dissect_rpcap_open_request (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_STARTCAP_REQ:
|
|
dissect_rpcap_startcap_request (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_UPDATEFILTER_REQ:
|
|
dissect_rpcap_filter (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_PACKET:
|
|
proto_item_set_len (ti, 28);
|
|
dissect_rpcap_packet (tvb, pinfo, top_tree, tree, offset, ti);
|
|
break;
|
|
case RPCAP_MSG_AUTH_REQ:
|
|
dissect_rpcap_auth_request (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_SETSAMPLING_REQ:
|
|
dissect_rpcap_sampling_request (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_AUTH_REPLY:
|
|
dissect_rpcap_auth_reply (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_FINDALLIF_REPLY:
|
|
dissect_rpcap_findalldevs_reply (tvb, pinfo, tree, offset, msg_value);
|
|
break;
|
|
case RPCAP_MSG_OPEN_REPLY:
|
|
dissect_rpcap_open_reply (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_STARTCAP_REPLY:
|
|
dissect_rpcap_startcap_reply (tvb, pinfo, tree, offset);
|
|
break;
|
|
case RPCAP_MSG_STATS_REPLY:
|
|
dissect_rpcap_stats_reply (tvb, pinfo, tree, offset);
|
|
break;
|
|
default:
|
|
len = tvb_reported_length_remaining (tvb, offset);
|
|
if (len) {
|
|
/* Yet unknown, dump as data */
|
|
proto_item_set_len (ti, 8);
|
|
new_tvb = tvb_new_subset_remaining (tvb, offset);
|
|
call_data_dissector(new_tvb, pinfo, top_tree);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
|
|
static gboolean
|
|
check_rpcap_heur (tvbuff_t *tvb, gboolean tcp)
|
|
{
|
|
gint offset = 0;
|
|
guint8 version, msg_type;
|
|
guint16 msg_value;
|
|
guint32 plen, len, caplen;
|
|
|
|
if (tvb_captured_length (tvb) < 8)
|
|
/* Too short */
|
|
return FALSE;
|
|
|
|
version = tvb_get_guint8 (tvb, offset);
|
|
if (version != 0)
|
|
/* Incorrect version */
|
|
return FALSE;
|
|
offset++;
|
|
|
|
msg_type = tvb_get_guint8 (tvb, offset);
|
|
if (!tcp && msg_type != 7) {
|
|
/* UDP is only used for packets */
|
|
return FALSE;
|
|
}
|
|
if (try_val_to_str(msg_type, message_type) == NULL)
|
|
/* Unknown message type */
|
|
return FALSE;
|
|
offset++;
|
|
|
|
msg_value = tvb_get_ntohs (tvb, offset);
|
|
if (msg_value > 0) {
|
|
if (msg_type == RPCAP_MSG_ERROR) {
|
|
/* Must have a valid error code */
|
|
if (try_val_to_str(msg_value, error_codes) == NULL)
|
|
return FALSE;
|
|
} else if (msg_type != RPCAP_MSG_FINDALLIF_REPLY) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
offset += 2;
|
|
|
|
plen = tvb_get_ntohl (tvb, offset);
|
|
offset += 4;
|
|
len = (guint32) tvb_reported_length_remaining (tvb, offset);
|
|
|
|
switch (msg_type) {
|
|
|
|
case RPCAP_MSG_FINDALLIF_REQ:
|
|
case RPCAP_MSG_UPDATEFILTER_REPLY:
|
|
case RPCAP_MSG_STATS_REQ:
|
|
case RPCAP_MSG_CLOSE:
|
|
case RPCAP_MSG_SETSAMPLING_REPLY:
|
|
case RPCAP_MSG_ENDCAP_REQ:
|
|
case RPCAP_MSG_ENDCAP_REPLY:
|
|
/* Empty payload */
|
|
if (plen != 0 || len != 0)
|
|
return FALSE;
|
|
break;
|
|
|
|
case RPCAP_MSG_OPEN_REPLY:
|
|
case RPCAP_MSG_STARTCAP_REPLY:
|
|
case RPCAP_MSG_SETSAMPLING_REQ:
|
|
/* Always 8 bytes */
|
|
if (plen != 8 || len != 8)
|
|
return FALSE;
|
|
break;
|
|
|
|
case RPCAP_MSG_STATS_REPLY:
|
|
/* Always 16 bytes */
|
|
if (plen != 16 || len != 16)
|
|
return FALSE;
|
|
break;
|
|
|
|
case RPCAP_MSG_PACKET:
|
|
/* Must have the frame header */
|
|
if (plen < 20)
|
|
return FALSE;
|
|
|
|
/* Check if capture length is valid */
|
|
caplen = tvb_get_ntohl (tvb, offset+8);
|
|
/* Always 20 bytes less than packet length */
|
|
if (caplen != (plen - 20) || caplen > 65535)
|
|
return FALSE;
|
|
break;
|
|
|
|
case RPCAP_MSG_FINDALLIF_REPLY:
|
|
case RPCAP_MSG_ERROR:
|
|
case RPCAP_MSG_OPEN_REQ:
|
|
case RPCAP_MSG_STARTCAP_REQ:
|
|
case RPCAP_MSG_UPDATEFILTER_REQ:
|
|
case RPCAP_MSG_AUTH_REQ:
|
|
case RPCAP_MSG_AUTH_REPLY:
|
|
/* Variable length */
|
|
if (plen != len)
|
|
return FALSE;
|
|
break;
|
|
default:
|
|
/* Unknown message type */
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static guint
|
|
get_rpcap_pdu_len (packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
|
|
{
|
|
return tvb_get_ntohl (tvb, offset + 4) + 8;
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_rpcap_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|
{
|
|
tcp_dissect_pdus (tvb, pinfo, tree, rpcap_desegment, 8,
|
|
get_rpcap_pdu_len, dissect_rpcap, data);
|
|
return tvb_captured_length (tvb);
|
|
}
|
|
|
|
static gboolean
|
|
dissect_rpcap_heur_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|
{
|
|
if (check_rpcap_heur (tvb, TRUE)) {
|
|
/*
|
|
* This is probably a rpcap TCP packet.
|
|
* Make the dissector for this conversation the non-heuristic
|
|
* rpcap dissector, so that malformed rpcap packets are reported
|
|
* as such.
|
|
*/
|
|
conversation_t *conversation = find_conversation_pinfo (pinfo, 0);
|
|
if (conversation)
|
|
conversation_set_dissector_from_frame_number (conversation,
|
|
pinfo->num,
|
|
rpcap_tcp_handle);
|
|
tcp_dissect_pdus (tvb, pinfo, tree, rpcap_desegment, 8,
|
|
get_rpcap_pdu_len, dissect_rpcap, data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static gboolean
|
|
dissect_rpcap_heur_udp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|
{
|
|
if (check_rpcap_heur (tvb, FALSE)) {
|
|
/* This is probably a rpcap udp package */
|
|
dissect_rpcap (tvb, pinfo, tree, data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void
|
|
proto_register_rpcap (void)
|
|
{
|
|
static hf_register_info hf[] = {
|
|
/* Common header for all messages */
|
|
{ &hf_version,
|
|
{ "Version", "rpcap.version", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_type,
|
|
{ "Message type", "rpcap.type", FT_UINT8, BASE_HEX,
|
|
VALS(message_type), 0x0, NULL, HFILL } },
|
|
{ &hf_value,
|
|
{ "Message value", "rpcap.value", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_plen,
|
|
{ "Payload length", "rpcap.len", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Error */
|
|
{ &hf_error,
|
|
{ "Error", "rpcap.error", FT_STRING, BASE_STR_WSP,
|
|
NULL, 0x0, "Error text", HFILL } },
|
|
{ &hf_error_value,
|
|
{ "Error value", "rpcap.error_value", FT_UINT16, BASE_DEC,
|
|
VALS(error_codes), 0x0, NULL, HFILL } },
|
|
|
|
/* Packet header */
|
|
{ &hf_packet,
|
|
{ "Packet", "rpcap.packet", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, "Packet data", HFILL } },
|
|
{ &hf_timestamp,
|
|
{ "Arrival time", "rpcap.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_caplen,
|
|
{ "Capture length", "rpcap.cap_len", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_len,
|
|
{ "Frame length", "rpcap.len", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, "Frame length (off wire)", HFILL } },
|
|
{ &hf_npkt,
|
|
{ "Frame number", "rpcap.number", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Authentication request */
|
|
{ &hf_auth_request,
|
|
{ "Authentication request", "rpcap.auth_request", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_type,
|
|
{ "Authentication type", "rpcap.auth_type", FT_UINT16, BASE_DEC,
|
|
VALS(auth_type), 0x0, NULL, HFILL } },
|
|
{ &hf_auth_slen1,
|
|
{ "Authentication item length 1", "rpcap.auth_len1", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_slen2,
|
|
{ "Authentication item length 2", "rpcap.auth_len2", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_username,
|
|
{ "Username", "rpcap.username", FT_STRING, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_password,
|
|
{ "Password", "rpcap.password", FT_STRING, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Authentication reply */
|
|
{ &hf_auth_reply,
|
|
{ "Authentication reply", "rpcap.auth_reply", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_minvers,
|
|
{ "Minimum version number supported", "rpcap.auth_minvers", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_auth_maxvers,
|
|
{ "Maximum version number supported", "rpcap.auth_maxvers", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Open request */
|
|
{ &hf_open_request,
|
|
{ "Open request", "rpcap.open_request", FT_STRING, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Open reply */
|
|
{ &hf_open_reply,
|
|
{ "Open reply", "rpcap.open_reply", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
/*
|
|
* XXX - the code probably sends a DLT_ value over the wire, but
|
|
* it should really send a LINKTYPE_ value, so that if the client
|
|
* and server are running OSes that disagree on the numerical value
|
|
* of that DLT_, they won't get confused (LINKTYPE_ values aren't
|
|
* platform-dependent). The vast majority of LINKTYPE_ values and
|
|
* DLT_ values are the same for the same link-layer type.
|
|
*/
|
|
{ &hf_linktype,
|
|
{ "Link type", "rpcap.linktype", FT_UINT32, BASE_DEC,
|
|
VALS(link_type_vals), 0x0, NULL, HFILL } },
|
|
{ &hf_tzoff,
|
|
{ "Timezone offset", "rpcap.tzoff", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Start capture request */
|
|
{ &hf_startcap_request,
|
|
{ "Start capture request", "rpcap.startcap_request", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_snaplen,
|
|
{ "Snap length", "rpcap.snaplen", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_read_timeout,
|
|
{ "Read timeout", "rpcap.read_timeout", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_flags,
|
|
{ "Flags", "rpcap.flags", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, "Capture flags", HFILL } },
|
|
{ &hf_flags_promisc,
|
|
{ "Promiscuous mode", "rpcap.flags.promisc", FT_BOOLEAN, 16,
|
|
TFS(&tfs_enabled_disabled), FLAG_PROMISC, NULL, HFILL } },
|
|
{ &hf_flags_dgram,
|
|
{ "Use Datagram", "rpcap.flags.dgram", FT_BOOLEAN, 16,
|
|
TFS(&tfs_yes_no), FLAG_DGRAM, NULL, HFILL } },
|
|
{ &hf_flags_serveropen,
|
|
{ "Server open", "rpcap.flags.serveropen", FT_BOOLEAN, 16,
|
|
TFS(&tfs_open_closed), FLAG_SERVEROPEN, NULL, HFILL } },
|
|
{ &hf_flags_inbound,
|
|
{ "Inbound", "rpcap.flags.inbound", FT_BOOLEAN, 16,
|
|
TFS(&tfs_yes_no), FLAG_INBOUND, NULL, HFILL } },
|
|
{ &hf_flags_outbound,
|
|
{ "Outbound", "rpcap.flags.outbound", FT_BOOLEAN, 16,
|
|
TFS(&tfs_yes_no), FLAG_OUTBOUND, NULL, HFILL } },
|
|
{ &hf_client_port,
|
|
{ "Client Port", "rpcap.client_port", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Start capture reply */
|
|
{ &hf_startcap_reply,
|
|
{ "Start capture reply", "rpcap.startcap_reply", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_bufsize,
|
|
{ "Buffer size", "rpcap.bufsize", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_server_port,
|
|
{ "Server port", "rpcap.server_port", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_dummy,
|
|
{ "Dummy", "rpcap.dummy", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Filter */
|
|
{ &hf_filter,
|
|
{ "Filter", "rpcap.filter", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_filtertype,
|
|
{ "Filter type", "rpcap.filtertype", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, "Filter type (BPF)", HFILL } },
|
|
{ &hf_nitems,
|
|
{ "Number of items", "rpcap.nitems", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Filter BPF instruction */
|
|
{ &hf_filterbpf_insn,
|
|
{ "Filter BPF instruction", "rpcap.filterbpf_insn", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_code,
|
|
{ "Op code", "rpcap.opcode", FT_UINT16, BASE_HEX,
|
|
NULL, 0x0, "Operation code", HFILL } },
|
|
{ &hf_code_class,
|
|
{ "Class", "rpcap.opcode.class", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_class), 0x07, "Instruction Class", HFILL } },
|
|
{ &hf_code_fields,
|
|
{ "Fields", "rpcap.opcode.fields", FT_UINT16, BASE_HEX,
|
|
NULL, 0xF8, "Class Fields", HFILL } },
|
|
{ &hf_code_ld_size,
|
|
{ "Size", "rpcap.opcode.size", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_size), 0x18, NULL, HFILL } },
|
|
{ &hf_code_ld_mode,
|
|
{ "Mode", "rpcap.opcode.mode", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_mode), 0xE0, NULL, HFILL } },
|
|
{ &hf_code_alu_op,
|
|
{ "Op", "rpcap.opcode.aluop", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_alu_op), 0xF0, NULL, HFILL } },
|
|
{ &hf_code_jmp_op,
|
|
{ "Op", "rpcap.opcode.jmpop", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_jmp_op), 0xF0, NULL, HFILL } },
|
|
{ &hf_code_src,
|
|
{ "Src", "rpcap.opcode.src", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_src), 0x08, NULL, HFILL } },
|
|
{ &hf_code_rval,
|
|
{ "Rval", "rpcap.opcode.rval", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_rval), 0x18, NULL, HFILL } },
|
|
{ &hf_code_misc_op,
|
|
{ "Op", "rpcap.opcode.miscop", FT_UINT16, BASE_HEX,
|
|
VALS(bpf_misc_op), 0xF8, NULL, HFILL } },
|
|
{ &hf_jt,
|
|
{ "JT", "rpcap.jt", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_jf,
|
|
{ "JF", "rpcap.jf", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_instr_value,
|
|
{ "Instruction value", "rpcap.instr_value", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, "Instruction-Dependent value", HFILL } },
|
|
|
|
/* Statistics reply */
|
|
{ &hf_stats_reply,
|
|
{ "Statistics", "rpcap.stats_reply", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, "Statistics reply data", HFILL } },
|
|
{ &hf_ifrecv,
|
|
{ "Received by kernel filter", "rpcap.ifrecv", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, "Received by kernel", HFILL } },
|
|
{ &hf_ifdrop,
|
|
{ "Dropped by network interface", "rpcap.ifdrop", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_krnldrop,
|
|
{ "Dropped by kernel filter", "rpcap.krnldrop", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_srvcapt,
|
|
{ "Captured by rpcapd", "rpcap.srvcapt", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, "Captured by RPCAP daemon", HFILL } },
|
|
|
|
/* Find all devices reply */
|
|
{ &hf_findalldevs_reply,
|
|
{ "Find all devices", "rpcap.findalldevs_reply", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_findalldevs_if,
|
|
{ "Interface", "rpcap.if", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_namelen,
|
|
{ "Name length", "rpcap.namelen", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_desclen,
|
|
{ "Description length", "rpcap.desclen", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_flags,
|
|
{ "Interface flags", "rpcap.if.flags", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_naddr,
|
|
{ "Number of addresses", "rpcap.naddr", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_name,
|
|
{ "Name", "rpcap.ifname", FT_STRING, BASE_NONE,
|
|
NULL, 0x0, "Interface name", HFILL } },
|
|
{ &hf_if_desc,
|
|
{ "Description", "rpcap.ifdesc", FT_STRING, BASE_NONE,
|
|
NULL, 0x0, "Interface description", HFILL } },
|
|
|
|
/* Find all devices / Interface addresses */
|
|
{ &hf_findalldevs_ifaddr,
|
|
{ "Interface address", "rpcap.ifaddr", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_addr,
|
|
{ "Address", "rpcap.addr", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, "Network address", HFILL } },
|
|
{ &hf_if_netmask,
|
|
{ "Netmask", "rpcap.netmask", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_broadaddr,
|
|
{ "Broadcast", "rpcap.broadaddr", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_dstaddr,
|
|
{ "P2P destination address", "rpcap.dstaddr", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_af,
|
|
{ "Address family", "rpcap.if.af", FT_UINT16, BASE_HEX,
|
|
VALS(address_family), 0x0, NULL, HFILL } },
|
|
{ &hf_if_port,
|
|
{ "Port", "rpcap.if.port", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, "Port number", HFILL } },
|
|
{ &hf_if_ipv4,
|
|
{ "IPv4 address", "rpcap.if.ipv4", FT_IPv4, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_flowinfo,
|
|
{ "Flow information", "rpcap.if.flowinfo", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_ipv6,
|
|
{ "IPv6 address", "rpcap.if.ipv6", FT_IPv6, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_scopeid,
|
|
{ "Scope ID", "rpcap.if.scopeid", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_padding,
|
|
{ "Padding", "rpcap.if.padding", FT_BYTES, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_if_unknown,
|
|
{ "Unknown address", "rpcap.if.unknown", FT_BYTES, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
|
|
/* Sampling request */
|
|
{ &hf_sampling_request,
|
|
{ "Sampling", "rpcap.sampling_request", FT_NONE, BASE_NONE,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_sampling_method,
|
|
{ "Method", "rpcap.sampling_method", FT_UINT8, BASE_DEC,
|
|
VALS(sampling_method), 0x0, "Sampling method", HFILL } },
|
|
{ &hf_sampling_dummy1,
|
|
{ "Dummy1", "rpcap.dummy", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_sampling_dummy2,
|
|
{ "Dummy2", "rpcap.dummy", FT_UINT16, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
{ &hf_sampling_value,
|
|
{ "Value", "rpcap.sampling_value", FT_UINT32, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL } },
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
&ett_rpcap,
|
|
&ett_error,
|
|
&ett_packet,
|
|
&ett_auth_request,
|
|
&ett_auth_reply,
|
|
&ett_open_reply,
|
|
&ett_startcap_request,
|
|
&ett_startcap_reply,
|
|
&ett_startcap_flags,
|
|
&ett_filter,
|
|
&ett_filterbpf_insn,
|
|
&ett_filterbpf_insn_code,
|
|
&ett_stats_reply,
|
|
&ett_findalldevs_reply,
|
|
&ett_findalldevs_if,
|
|
&ett_findalldevs_ifaddr,
|
|
&ett_ifaddr,
|
|
&ett_sampling_request
|
|
};
|
|
|
|
static ei_register_info ei[] = {
|
|
{ &ei_error, { "rpcap.error.expert", PI_SEQUENCE, PI_NOTE, "Error", EXPFILL }},
|
|
{ &ei_if_unknown, { "rpcap.if_unknown", PI_SEQUENCE, PI_NOTE, "Unknown address family", EXPFILL }},
|
|
{ &ei_no_more_data, { "rpcap.no_more_data", PI_MALFORMED, PI_ERROR, "No more data in packet", EXPFILL }},
|
|
{ &ei_caplen_too_big, { "rpcap.caplen_too_big", PI_MALFORMED, PI_ERROR, "Caplen is bigger than the remaining message length", EXPFILL }},
|
|
};
|
|
|
|
module_t *rpcap_module;
|
|
expert_module_t* expert_rpcap;
|
|
|
|
proto_rpcap = proto_register_protocol (PNAME, PSNAME, PFNAME);
|
|
register_dissector (PFNAME, dissect_rpcap, proto_rpcap);
|
|
expert_rpcap = expert_register_protocol(proto_rpcap);
|
|
expert_register_field_array(expert_rpcap, ei, array_length(ei));
|
|
|
|
proto_register_field_array (proto_rpcap, hf, array_length (hf));
|
|
proto_register_subtree_array (ett, array_length (ett));
|
|
|
|
/* Register our configuration options */
|
|
rpcap_module = prefs_register_protocol (proto_rpcap, proto_reg_handoff_rpcap);
|
|
|
|
prefs_register_bool_preference (rpcap_module, "desegment_pdus",
|
|
"Reassemble PDUs spanning multiple TCP segments",
|
|
"Whether the RPCAP dissector should reassemble PDUs"
|
|
" spanning multiple TCP segments."
|
|
" To use this option, you must also enable \"Allow subdissectors"
|
|
" to reassemble TCP streams\" in the TCP protocol settings.",
|
|
&rpcap_desegment);
|
|
prefs_register_bool_preference (rpcap_module, "decode_content",
|
|
"Decode content according to link-layer type",
|
|
"Whether the packets should be decoded according to"
|
|
" the link-layer type.",
|
|
&decode_content);
|
|
prefs_register_uint_preference (rpcap_module, "linktype",
|
|
"Default link-layer type",
|
|
"Default link-layer type to use if an Open Reply packet"
|
|
" has not been captured.",
|
|
10, &global_linktype);
|
|
}
|
|
|
|
void
|
|
proto_reg_handoff_rpcap (void)
|
|
{
|
|
static gboolean rpcap_prefs_initialized = FALSE;
|
|
|
|
if (!rpcap_prefs_initialized) {
|
|
pcap_pktdata_handle = find_dissector_add_dependency("pcap_pktdata", proto_rpcap);
|
|
rpcap_prefs_initialized = TRUE;
|
|
|
|
heur_dissector_add ("tcp", dissect_rpcap_heur_tcp, "RPCAP over TCP", "rpcap_tcp", proto_rpcap, HEURISTIC_ENABLE);
|
|
heur_dissector_add ("udp", dissect_rpcap_heur_udp, "RPCAP over UDP", "rpcap_udp", proto_rpcap, HEURISTIC_ENABLE);
|
|
|
|
rpcap_tcp_handle = create_dissector_handle(dissect_rpcap_tcp, proto_rpcap);
|
|
}
|
|
|
|
info_added = FALSE;
|
|
linktype = global_linktype;
|
|
}
|
|
|
|
/*
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local Variables:
|
|
* c-basic-offset: 2
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* ex: set shiftwidth=2 tabstop=8 expandtab:
|
|
* :indentSize=2:tabSize=8:noTabs=true:
|
|
*/
|