summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-winsrepl.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-winsrepl.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-winsrepl.c')
-rw-r--r--epan/dissectors/packet-winsrepl.c882
1 files changed, 882 insertions, 0 deletions
diff --git a/epan/dissectors/packet-winsrepl.c b/epan/dissectors/packet-winsrepl.c
new file mode 100644
index 00000000..d4d443be
--- /dev/null
+++ b/epan/dissectors/packet-winsrepl.c
@@ -0,0 +1,882 @@
+/*
+ * packet-winsrepl.c
+ *
+ * Routines for WINS Replication packet dissection
+ *
+ * Copyright 2005 Stefan Metzmacher <metze@samba.org>
+ *
+ * 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/expert.h>
+#include <epan/exceptions.h>
+#include <epan/prefs.h>
+#include <epan/to_str.h>
+
+#include "packet-netbios.h"
+
+#include "packet-tcp.h"
+
+void proto_register_winsrepl(void);
+void proto_reg_handoff_winsrepl(void);
+static dissector_handle_t winsrepl_handle;
+
+static gboolean winsrepl_reassemble = TRUE;
+
+static int proto_winsrepl = -1;
+
+static int hf_winsrepl_size = -1;
+static int hf_winsrepl_opcode = -1;
+static int hf_winsrepl_assoc_ctx = -1;
+static int hf_winsrepl_mess_type = -1;
+
+static int hf_winsrepl_start_minor_version = -1;
+static int hf_winsrepl_start_major_version = -1;
+
+static int hf_winsrepl_stop_reason = -1;
+
+static int hf_winsrepl_replication_command = -1;
+
+static int hf_winsrepl_owner_address = -1;
+static int hf_winsrepl_owner_max_version = -1;
+static int hf_winsrepl_owner_min_version = -1;
+static int hf_winsrepl_owner_type = -1;
+
+static int hf_winsrepl_table_partner_count = -1;
+static int hf_winsrepl_table_initiator = -1;
+
+static int hf_winsrepl_ip_owner = -1;
+static int hf_winsrepl_ip_ip = -1;
+static int hf_winsrepl_addr_list_num_ips = -1;
+
+static int hf_winsrepl_name_len = -1;
+static int hf_winsrepl_name_flags = -1;
+static int hf_winsrepl_name_flags_rectype = -1;
+static int hf_winsrepl_name_flags_recstate = -1;
+static int hf_winsrepl_name_flags_local = -1;
+static int hf_winsrepl_name_flags_hosttype = -1;
+static int hf_winsrepl_name_flags_static = -1;
+static int hf_winsrepl_name_group_flag = -1;
+static int hf_winsrepl_name_version_id = -1;
+static int hf_winsrepl_name_unknown = -1;
+
+static int hf_winsrepl_reply_num_names = -1;
+
+static gint ett_winsrepl = -1;
+
+static gint ett_winsrepl_start = -1;
+static gint ett_winsrepl_stop = -1;
+static gint ett_winsrepl_replication = -1;
+
+static gint ett_winsrepl_owner = -1;
+static gint ett_winsrepl_table_reply = -1;
+
+static gint ett_winsrepl_ip = -1;
+static gint ett_winsrepl_addr_list = -1;
+
+static gint ett_winsrepl_name = -1;
+static gint ett_winsrepl_send_reply = -1;
+
+static gint ett_winsrepl_flags = -1;
+
+static expert_field ei_winsrepl_name_len = EI_INIT;
+
+#define WINS_REPLICATION_PORT ( 42 )
+#define WREPL_OPCODE_BITS ( 0x7800 )
+
+enum wrepl_replication_cmd {
+ WREPL_REPL_TABLE_QUERY=0,
+ WREPL_REPL_TABLE_REPLY=1,
+ WREPL_REPL_SEND_REQUEST=2,
+ WREPL_REPL_SEND_REPLY=3,
+ WREPL_REPL_UPDATE=4,
+ WREPL_REPL_UPDATE2=5,
+ WREPL_REPL_INFORM=8,
+ WREPL_REPL_INFORM2=9
+};
+
+enum wrepl_mess_type {
+ WREPL_START_ASSOCIATION=0,
+ WREPL_START_ASSOCIATION_REPLY=1,
+ WREPL_STOP_ASSOCIATION=2,
+ WREPL_REPLICATION=3
+};
+
+static const value_string replication_cmd_vals[] = {
+ {WREPL_REPL_TABLE_QUERY, "WREPL_REPL_TABLE_QUERY"},
+ {WREPL_REPL_TABLE_REPLY, "WREPL_REPL_TABLE_REPLY"},
+ {WREPL_REPL_SEND_REQUEST, "WREPL_REPL_SEND_REQUEST"},
+ {WREPL_REPL_SEND_REPLY, "WREPL_REPL_SEND_REPLY"},
+ {WREPL_REPL_UPDATE, "WREPL_REPL_UPDATE"},
+ {WREPL_REPL_UPDATE2, "WREPL_REPL_UPDATE2"},
+ {WREPL_REPL_INFORM, "WREPL_REPL_INFORM"},
+ {WREPL_REPL_INFORM2, "WREPL_REPL_INFORM2"},
+ {0, NULL}
+};
+
+static const value_string message_type_vals[] = {
+ {WREPL_START_ASSOCIATION, "WREPL_START_ASSOCIATION"},
+ {WREPL_START_ASSOCIATION_REPLY, "WREPL_START_ASSOCIATION_REPLY"},
+ {WREPL_STOP_ASSOCIATION, "WREPL_STOP_ASSOCIATION"},
+ {WREPL_REPLICATION, "WREPL_REPLICATION"},
+ {0, NULL}
+};
+
+#define WREPL_NAME_TYPE_MASK 0x03
+
+#define WREPL_NAME_TYPE_UNIQUE 0x00
+#define WREPL_NAME_TYPE_NORMAL_GROUP 0x01
+#define WREPL_NAME_TYPE_SPECIAL_GROUP 0x02
+#define WREPL_NAME_TYPE_MULTIHOMED 0x03
+
+static const value_string rectype_vals[] = {
+ {WREPL_NAME_TYPE_UNIQUE, "Unique"},
+ {WREPL_NAME_TYPE_NORMAL_GROUP, "Normal group"},
+ {WREPL_NAME_TYPE_SPECIAL_GROUP, "Special group"},
+ {WREPL_NAME_TYPE_MULTIHOMED, "Multihomed"},
+ {0, NULL}
+};
+
+static const value_string recstate_vals[] = {
+ {0x00, "Active"},
+ {0x01, "Released"},
+ {0x02, "Tombstoned"},
+ {0x03, "Deleted"},
+ {0, NULL}
+};
+
+static const value_string hosttype_vals[] = {
+ {0x00, "B-node"},
+ {0x01, "P-node"},
+ {0x02, "M-node"},
+ {0x03, "H-node"},
+ {0, NULL}
+};
+
+static int
+dissect_winsrepl_start(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ proto_tree *start_tree;
+
+ start_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_start, NULL, "WREPL_START_ASSOCIATION");
+
+ /* ASSOC_CTX */
+ proto_tree_add_item(start_tree, hf_winsrepl_assoc_ctx, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ /* MINOR VERSION */
+ proto_tree_add_item(start_tree, hf_winsrepl_start_minor_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
+ winsrepl_offset += 2;
+
+ /* MAJOR VERSION */
+ proto_tree_add_item(start_tree, hf_winsrepl_start_major_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
+ winsrepl_offset += 2;
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_stop(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ guint32 reason;
+ proto_item *stop_item;
+ proto_tree *stop_tree;
+
+ stop_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_stop, &stop_item, "WREPL_STOP_ASSOCIATION");
+
+ /* REASON */
+ reason = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_uint(stop_tree, hf_winsrepl_stop_reason, winsrepl_tvb, winsrepl_offset, 4, reason);
+ winsrepl_offset += 4;
+
+ proto_item_append_text(stop_item, ", Reason: 0x%08X", reason);
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_table_query(tvbuff_t *winsrepl_tvb _U_, packet_info *pinfo _U_,
+ int winsrepl_offset, proto_tree *winsrepl_tree _U_)
+{
+ /* Nothing to do here */
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_wins_owner(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree,
+ proto_tree *sub_tree, guint32 idx)
+{
+ proto_tree *owner_tree = NULL;
+
+ if (sub_tree) {
+ owner_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 24,
+ ett_winsrepl_owner, NULL, "WINS Owner [%u]", idx);
+ } else if (winsrepl_tree) {
+ owner_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 24,
+ ett_winsrepl_owner, NULL, "WINS Owner");
+ }
+
+ /* ADDRESS */
+ proto_tree_add_item(owner_tree, hf_winsrepl_owner_address, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ /* MAX_VERSION */
+ proto_tree_add_item(owner_tree, hf_winsrepl_owner_max_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
+ winsrepl_offset += 8;
+
+ /* MIN_VERSION */
+ proto_tree_add_item(owner_tree, hf_winsrepl_owner_min_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
+ winsrepl_offset += 8;
+
+ /* TYPE */
+ proto_tree_add_item(owner_tree, hf_winsrepl_owner_type, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_table_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ proto_tree *table_tree;
+ guint32 partner_count;
+ guint32 i;
+
+ table_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_table_reply, NULL, "WREPL_REPL_TABLE_REPLY");
+
+ /* PARTNER COUNT */
+ partner_count = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_uint(table_tree, hf_winsrepl_table_partner_count, winsrepl_tvb, winsrepl_offset, 4, partner_count);
+ winsrepl_offset += 4;
+
+ for (i=0; i < partner_count; i++) {
+ winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
+ winsrepl_offset, table_tree,
+ table_tree, i);
+ }
+
+ /* INITIATOR */
+ proto_tree_add_item(table_tree, hf_winsrepl_table_initiator, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_send_request(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
+ winsrepl_offset, winsrepl_tree,
+ NULL, 0);
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_wins_ip(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree,
+ guint32 *addr, proto_tree *sub_tree, guint32 idx)
+{
+ proto_item *ip_item = NULL;
+ proto_tree *ip_tree = NULL;
+
+ if (sub_tree) {
+ ip_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 8,
+ ett_winsrepl_ip, &ip_item, "WINS IP [%u]", idx);
+ } else if (winsrepl_tree) {
+ ip_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 8,
+ ett_winsrepl_ip, &ip_item, "WINS IP");
+ }
+
+ /* OWNER */
+ proto_tree_add_item(ip_tree, hf_winsrepl_ip_owner, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ /* IP */
+ *addr = tvb_get_ipv4(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_ipv4(ip_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, *addr);
+ proto_item_append_text(ip_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
+ winsrepl_offset += 4;
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_wins_address_list(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree,
+ proto_item *parent_item)
+{
+ proto_item *addr_list_item;
+ proto_tree *addr_list_tree;
+ int old_offset = winsrepl_offset;
+ guint32 num_ips;
+ guint32 ip;
+ guint32 i;
+ address addr;
+ gchar* addr_str;
+
+ addr_list_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_addr_list, &addr_list_item, "WINS Address List");
+
+ /* NUM_IPS */
+ num_ips = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_uint(addr_list_tree, hf_winsrepl_addr_list_num_ips, winsrepl_tvb, winsrepl_offset, 4, num_ips);
+ winsrepl_offset += 4;
+
+ for (i=0; i < num_ips; i++) {
+ winsrepl_offset = dissect_winsrepl_wins_ip(winsrepl_tvb, pinfo,
+ winsrepl_offset, addr_list_tree,
+ &ip, addr_list_tree, i);
+ set_address(&addr, AT_IPv4, 4, &ip);
+ addr_str = address_to_str(pinfo->pool, &addr);
+ if (i == 0) {
+ proto_item_append_text(parent_item, ": %s", addr_str);
+ proto_item_append_text(addr_list_item, ": %s", addr_str);
+ } else {
+ proto_item_append_text(parent_item, ", %s", addr_str);
+ proto_item_append_text(addr_list_item, ", %s", addr_str);
+ }
+ }
+
+ proto_item_set_len(addr_list_item, winsrepl_offset - old_offset);
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_wins_name(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree,
+ proto_tree *sub_tree, guint32 idx)
+{
+ proto_item *name_item = NULL, *ti;
+ proto_tree *name_tree = NULL;
+ int old_offset = winsrepl_offset;
+ tvbuff_t *name_tvb = NULL;
+ guint32 name_len;
+ char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ guint32 flags;
+ static int * const name_flags[] = {
+ &hf_winsrepl_name_flags_rectype,
+ &hf_winsrepl_name_flags_recstate,
+ &hf_winsrepl_name_flags_local,
+ &hf_winsrepl_name_flags_hosttype,
+ &hf_winsrepl_name_flags_static,
+ NULL
+ };
+
+ if (sub_tree) {
+ name_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_name, &name_item, "WINS Name [%u]", idx);
+ } else if (winsrepl_tree) {
+ name_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_name, &name_item, "WINS Name");
+ }
+
+ /* NAME_LEN */
+ name_len = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ ti = proto_tree_add_uint(name_tree, hf_winsrepl_name_len, winsrepl_tvb, winsrepl_offset, 4, name_len);
+ winsrepl_offset += 4;
+ if (name_len == 0) {
+ expert_add_info(pinfo, ti, &ei_winsrepl_name_len);
+ return winsrepl_offset;
+ }
+
+ /* NAME: TODO! */
+ /*
+ * XXX - apparently, according to the Samba code for handling
+ * WINS replication, there's a bug in a lot of versions of Windows,
+ * including W2K SP2, wherein the first and last bytes of the
+ * name (the last byte being the name type) are swapped if
+ * the type is 0x1b. I think I've seen this in at least
+ * one capture.
+ */
+ name_tvb = tvb_new_subset_length(winsrepl_tvb, winsrepl_offset, name_len);
+ netbios_add_name("Name", name_tvb, 0, name_tree);
+ name_type = get_netbios_name(name_tvb, 0, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
+ proto_item_append_text(name_item, ": %s<%02x>", name_str, name_type);
+ winsrepl_offset += name_len;
+
+ /* ALIGN to 4 Byte */
+ /* winsrepl_offset += ((winsrepl_offset & (4-1)) == 0 ? 0 : (4 - (winsrepl_offset & (4-1)))); */
+ /* Windows including w2k8 add 4 padding bytes, when it's already 4 byte
+ * aligned... This happens when the name has a "scope" part
+ */
+ winsrepl_offset += 4 - (winsrepl_offset & (4-1));
+
+ /* FLAGS */
+ /*
+ * XXX - there appear to be more flag bits, but I didn't see
+ * anything in the Samba code about them.
+ */
+ flags = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_bitmask(name_tree, winsrepl_tvb, winsrepl_offset, hf_winsrepl_name_flags, ett_winsrepl_flags, name_flags, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ /* GROUP_FLAG */
+ /* XXX - is this just a Boolean? */
+ proto_tree_add_item(name_tree, hf_winsrepl_name_group_flag, winsrepl_tvb, winsrepl_offset, 4, ENC_LITTLE_ENDIAN);
+ winsrepl_offset += 4;
+
+ /* Version ID */
+ proto_tree_add_item(name_tree, hf_winsrepl_name_version_id, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
+ winsrepl_offset += 8;
+
+ switch (flags & WREPL_NAME_TYPE_MASK) {
+
+ case WREPL_NAME_TYPE_UNIQUE:
+ case WREPL_NAME_TYPE_NORMAL_GROUP:
+ /* Single address */
+ proto_tree_add_item(name_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ proto_item_append_text(name_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
+ winsrepl_offset += 4;
+ break;
+
+ case WREPL_NAME_TYPE_SPECIAL_GROUP:
+ case WREPL_NAME_TYPE_MULTIHOMED:
+ /* Address list */
+ winsrepl_offset = dissect_winsrepl_wins_address_list(winsrepl_tvb, pinfo,
+ winsrepl_offset, name_tree,
+ name_item);
+ break;
+ }
+
+ /* UNKNOWN, little or big endian??? */
+ proto_tree_add_item(name_tree, hf_winsrepl_name_unknown, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
+ winsrepl_offset += 4;
+
+ proto_item_set_len(name_item, winsrepl_offset - old_offset);
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_send_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ proto_tree *rep_tree;
+ guint32 num_names;
+ guint32 i;
+
+ rep_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_send_reply, NULL, "WREPL_REPL_SEND_REPLY");
+
+ /* NUM NAMES */
+ num_names = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_uint(rep_tree, hf_winsrepl_reply_num_names, winsrepl_tvb, winsrepl_offset, 4, num_names);
+ winsrepl_offset += 4;
+
+ for (i=0; i < num_names; i++) {
+ winsrepl_offset = dissect_winsrepl_wins_name(winsrepl_tvb, pinfo,
+ winsrepl_offset, rep_tree,
+ rep_tree, i);
+ }
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_update(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, winsrepl_tree);
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_update2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, winsrepl_tree);
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_inform(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, winsrepl_tree);
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_inform2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_tree *winsrepl_tree)
+{
+ winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, winsrepl_tree);
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_replication(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
+ int winsrepl_offset, proto_item *winsrepl_item, proto_tree *winsrepl_tree)
+{
+ proto_item *repl_item;
+ proto_tree *repl_tree;
+ enum wrepl_replication_cmd command;
+
+ repl_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
+ ett_winsrepl_replication, &repl_item, "WREPL_REPLICATION");
+
+ /* REPLICATION_CMD */
+ command = (enum wrepl_replication_cmd)tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
+ proto_tree_add_uint(repl_tree, hf_winsrepl_replication_command, winsrepl_tvb, winsrepl_offset, 4, command);
+ winsrepl_offset += 4;
+
+ switch (command) {
+ case WREPL_REPL_TABLE_QUERY:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_QUERY");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_QUERY");
+ proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_QUERY");
+ winsrepl_offset = dissect_winsrepl_table_query(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_TABLE_REPLY:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_REPLY");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_REPLY");
+ proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_REPLY");
+ winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_SEND_REQUEST:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REQUEST");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REQUEST");
+ proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REQUEST");
+ winsrepl_offset = dissect_winsrepl_send_request(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_SEND_REPLY:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REPLY");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REPLY");
+ proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REPLY");
+ winsrepl_offset = dissect_winsrepl_send_reply(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_UPDATE:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_UPDATE");
+ proto_item_append_text(repl_item, ", WREPL_REPL_UPDATE");
+ winsrepl_offset = dissect_winsrepl_update(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_UPDATE2:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE2");
+ proto_item_append_text(winsrepl_item, ",WREPL_REPL_UPDATE2");
+ proto_item_append_text(repl_item, ",WREPL_REPL_UPDATE2");
+ winsrepl_offset = dissect_winsrepl_update2(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_INFORM:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM");
+ proto_item_append_text(repl_item, ", WREPL_REPL_INFORM");
+ winsrepl_offset = dissect_winsrepl_inform(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ case WREPL_REPL_INFORM2:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM2");
+ proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM2");
+ proto_item_append_text(repl_item, ", WREPL_REPL_INFORM2");
+ winsrepl_offset = dissect_winsrepl_inform2(winsrepl_tvb, pinfo,
+ winsrepl_offset, repl_tree);
+ break;
+ }
+
+ return winsrepl_offset;
+}
+
+static int
+dissect_winsrepl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
+{
+ int offset = 0;
+ proto_item *winsrepl_item;
+ proto_tree *winsrepl_tree;
+ enum wrepl_mess_type mess_type;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WINS-Replication");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ winsrepl_item = proto_tree_add_item(parent_tree, proto_winsrepl, tvb, offset, -1, ENC_NA);
+ winsrepl_tree = proto_item_add_subtree(winsrepl_item, ett_winsrepl);
+
+ /* SIZE */
+ proto_tree_add_item(winsrepl_tree, hf_winsrepl_size, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* OPCODE */
+ proto_tree_add_item(winsrepl_tree, hf_winsrepl_opcode, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* ASSOC_CTX */
+ proto_tree_add_item(winsrepl_tree, hf_winsrepl_assoc_ctx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* MESSAGE_TYPE */
+ mess_type = (enum wrepl_mess_type)tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(winsrepl_tree, hf_winsrepl_mess_type, tvb, offset, 4, mess_type);
+ offset += 4;
+
+ switch (mess_type) {
+ case WREPL_START_ASSOCIATION:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION");
+ proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION");
+ dissect_winsrepl_start(tvb, pinfo,
+ offset, winsrepl_tree);
+ break;
+ case WREPL_START_ASSOCIATION_REPLY:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION_REPLY");
+ proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION_REPLY");
+ dissect_winsrepl_start(tvb, pinfo,
+ offset, winsrepl_tree);
+ break;
+ case WREPL_STOP_ASSOCIATION:
+ col_set_str(pinfo->cinfo, COL_INFO, "WREPL_STOP_ASSOCIATION");
+ proto_item_append_text(winsrepl_item, ", WREPL_STOP_ASSOCIATION");
+ dissect_winsrepl_stop(tvb, pinfo,
+ offset, winsrepl_tree);
+ break;
+ case WREPL_REPLICATION:
+ dissect_winsrepl_replication(tvb, pinfo,
+ offset, winsrepl_item, winsrepl_tree);
+ break;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static guint
+get_winsrepl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
+ int offset, void *data _U_)
+{
+ guint pdu_len;
+
+ pdu_len=tvb_get_ntohl(tvb, offset);
+ return pdu_len+4;
+}
+
+static int
+dissect_winsrepl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
+{
+ tcp_dissect_pdus(tvb, pinfo, parent_tree, winsrepl_reassemble, 4, get_winsrepl_pdu_len, dissect_winsrepl_pdu, data);
+ return tvb_captured_length(tvb);
+}
+
+void
+proto_register_winsrepl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_winsrepl_size, {
+ "Packet Size", "winsrepl.size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Packet Size", HFILL }},
+
+ { &hf_winsrepl_opcode, {
+ "Opcode", "winsrepl.opcode",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "WINS Replication Opcode", HFILL }},
+
+ { &hf_winsrepl_assoc_ctx, {
+ "Assoc_Ctx", "winsrepl.assoc_ctx",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "WINS Replication Assoc_Ctx", HFILL }},
+
+ { &hf_winsrepl_mess_type, {
+ "Message_Type", "winsrepl.message_type",
+ FT_UINT32, BASE_DEC, VALS(message_type_vals), 0x0,
+ "WINS Replication Message_Type", HFILL }},
+
+ { &hf_winsrepl_start_minor_version, {
+ "Minor Version", "winsrepl.minor_version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "WINS Replication Minor Version", HFILL }},
+
+ { &hf_winsrepl_start_major_version, {
+ "Major Version", "winsrepl.major_version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "WINS Replication Major Version", HFILL }},
+
+ { &hf_winsrepl_stop_reason, {
+ "Reason", "winsrepl.reason",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "WINS Replication Reason", HFILL }},
+
+ { &hf_winsrepl_replication_command, {
+ "Replication Command", "winsrepl.repl_cmd",
+ FT_UINT32, BASE_HEX, VALS(replication_cmd_vals), 0x0,
+ "WINS Replication Command", HFILL }},
+
+ { &hf_winsrepl_owner_address, {
+ "Owner Address", "winsrepl.owner_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "WINS Replication Owner Address", HFILL }},
+
+ { &hf_winsrepl_owner_max_version, {
+ "Max Version", "winsrepl.max_version",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "WINS Replication Max Version", HFILL }},
+
+ { &hf_winsrepl_owner_min_version, {
+ "Min Version", "winsrepl.min_version",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "WINS Replication Min Version", HFILL }},
+
+ { &hf_winsrepl_owner_type, {
+ "Owner Type", "winsrepl.owner_type",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Owner Type", HFILL }},
+
+ { &hf_winsrepl_table_partner_count, {
+ "Partner Count", "winsrepl.partner_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Partner Count", HFILL }},
+
+ { &hf_winsrepl_table_initiator, {
+ "Initiator", "winsrepl.initiator",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "WINS Replication Initiator", HFILL }},
+
+ { &hf_winsrepl_ip_owner, {
+ "IP Owner", "winsrepl.ip_owner",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "WINS Replication IP Owner", HFILL }},
+
+ { &hf_winsrepl_ip_ip, {
+ "IP Address", "winsrepl.ip_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "WINS Replication IP Address", HFILL }},
+
+ { &hf_winsrepl_addr_list_num_ips, {
+ "Num IPs", "winsrepl.num_ips",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Num IPs", HFILL }},
+
+ { &hf_winsrepl_name_len, {
+ "Name Len", "winsrepl.name_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Name Len", HFILL }},
+
+ { &hf_winsrepl_name_flags, {
+ "Name Flags", "winsrepl.name_flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "WINS Replication Name Flags", HFILL }},
+
+ { &hf_winsrepl_name_flags_rectype, {
+ "Record Type", "winsrepl.name_flags.rectype",
+ FT_UINT32, BASE_HEX, VALS(rectype_vals), 0x00000003,
+ "WINS Replication Name Flags Record Type", HFILL }},
+
+ { &hf_winsrepl_name_flags_recstate, {
+ "Record State", "winsrepl.name_flags.recstate",
+ FT_UINT32, BASE_HEX, VALS(recstate_vals), 0x0000000C,
+ "WINS Replication Name Flags Record State", HFILL }},
+
+ { &hf_winsrepl_name_flags_local, {
+ "Local", "winsrepl.name_flags.local",
+ FT_BOOLEAN, 32, NULL, 0x00000010,
+ "WINS Replication Name Flags Local Flag", HFILL }},
+
+ { &hf_winsrepl_name_flags_hosttype, {
+ "Host Type", "winsrepl.name_flags.hosttype",
+ FT_UINT32, BASE_HEX, VALS(hosttype_vals), 0x00000060,
+ "WINS Replication Name Flags Host Type", HFILL }},
+
+ { &hf_winsrepl_name_flags_static, {
+ "Static", "winsrepl.name_flags.static",
+ FT_BOOLEAN, 32, NULL, 0x00000080,
+ "WINS Replication Name Flags Static Flag", HFILL }},
+
+ { &hf_winsrepl_name_group_flag, {
+ "Name Group Flag", "winsrepl.name_group_flag",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "WINS Replication Name Group Flag", HFILL }},
+
+ { &hf_winsrepl_name_version_id, {
+ "Name Version Id", "winsrepl.name_version_id",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "WINS Replication Name Version Id", HFILL }},
+
+ { &hf_winsrepl_name_unknown, {
+ "Unknown IP", "winsrepl.unknown",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "WINS Replication Unknown IP", HFILL }},
+
+ { &hf_winsrepl_reply_num_names, {
+ "Num Names", "winsrepl.num_names",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "WINS Replication Num Names", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_winsrepl,
+ &ett_winsrepl_start,
+ &ett_winsrepl_stop,
+ &ett_winsrepl_replication,
+ &ett_winsrepl_owner,
+ &ett_winsrepl_table_reply,
+ &ett_winsrepl_ip,
+ &ett_winsrepl_addr_list,
+ &ett_winsrepl_name,
+ &ett_winsrepl_send_reply,
+ &ett_winsrepl_flags,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_winsrepl_name_len, { "winsrepl.name_len.invalid", PI_MALFORMED, PI_ERROR, "Bad name length", EXPFILL }},
+ };
+
+ module_t *winsrepl_module;
+ expert_module_t* expert_winsrepl;
+
+ proto_winsrepl = proto_register_protocol("WINS (Windows Internet Name Service) Replication",
+ "WINS-Replication", "winsrepl");
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_winsrepl, hf, array_length(hf));
+ expert_winsrepl = expert_register_protocol(proto_winsrepl);
+ expert_register_field_array(expert_winsrepl, ei, array_length(ei));
+ winsrepl_handle = register_dissector("winsrepl", dissect_winsrepl, proto_winsrepl);
+
+ winsrepl_module = prefs_register_protocol(proto_winsrepl, NULL);
+ prefs_register_bool_preference(winsrepl_module, "reassemble",
+ "Reassemble WINS-Replication messages spanning multiple TCP segments",
+ "Whether the WINS-Replication dissector should reassemble messages spanning multiple TCP segments."
+ " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &winsrepl_reassemble);
+}
+
+void
+proto_reg_handoff_winsrepl(void)
+{
+ dissector_add_uint_with_preference("tcp.port", WINS_REPLICATION_PORT, winsrepl_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */