4 * Routines for WINS Replication packet dissection
6 * Copyright 2005 Stefan Metzmacher <metze@samba.org>
10 * Ethereal - Network traffic analyzer
11 * By Gerald Combs <gerald@ethereal.com>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
40 #include <epan/conversation.h>
41 #include <epan/strutil.h>
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
46 #include "packet-windows-common.h"
47 #include "packet-netbios.h"
49 #include "packet-winsrepl.h"
51 static gboolean winsrepl_reassemble = TRUE;
53 struct winsrepl_frame_data {
57 static int proto_winsrepl = -1;
59 static int hf_winsrepl_size = -1;
60 static int hf_winsrepl_opcode = -1;
61 static int hf_winsrepl_assoc_ctx = -1;
62 static int hf_winsrepl_mess_type = -1;
64 static int hf_winsrepl_start_minor_version = -1;
65 static int hf_winsrepl_start_major_version = -1;
67 static int hf_winsrepl_stop_reason = -1;
69 static int hf_winsrepl_replication_command = -1;
71 static int hf_winsrepl_owner_address = -1;
72 static int hf_winsrepl_owner_max_version = -1;
73 static int hf_winsrepl_owner_min_version = -1;
74 static int hf_winsrepl_owner_type = -1;
76 static int hf_winsrepl_table_partner_count = -1;
77 static int hf_winsrepl_table_initiator = -1;
79 static int hf_winsrepl_ip_owner = -1;
80 static int hf_winsrepl_ip_ip = -1;
81 static int hf_winsrepl_addr_list_num_ips = -1;
83 static int hf_winsrepl_name_len = -1;
84 static int hf_winsrepl_name_flags = -1;
85 static int hf_winsrepl_name_group_flag = -1;
86 static int hf_winsrepl_name_id = -1;
87 static int hf_winsrepl_name_unknown = -1;
89 static int hf_winsrepl_reply_num_names = -1;
91 static gint ett_winsrepl = -1;
93 static gint ett_winsrepl_start = -1;
94 static gint ett_winsrepl_stop = -1;
95 static gint ett_winsrepl_replication = -1;
97 static gint ett_winsrepl_owner = -1;
98 static gint ett_winsrepl_table_reply = -1;
100 static gint ett_winsrepl_ip = -1;
101 static gint ett_winsrepl_addr_list = -1;
103 static gint ett_winsrepl_name = -1;
104 static gint ett_winsrepl_send_reply = -1;
106 dissector_handle_t winsrepl_handle;
108 static unsigned int glb_winsrepl_tcp_port = WINS_REPLICATION_PORT;
110 static const value_string replication_cmd_vals[] = {
111 {WREPL_REPL_TABLE_QUERY, "WREPL_REPL_TABLE_QUERY"},
112 {WREPL_REPL_TABLE_REPLY, "WREPL_REPL_TABLE_REPLY"},
113 {WREPL_REPL_SEND_REQUEST, "WREPL_REPL_SEND_REQUEST"},
114 {WREPL_REPL_SEND_REPLY, "WREPL_REPL_SEND_REPLY"},
115 {WREPL_REPL_UPDATE, "WREPL_REPL_UPDATE"},
116 {WREPL_REPL_INFORM, "WREPL_REPL_INFORM"},
120 static const value_string message_type_vals[] = {
121 {WREPL_START_ASSOCIATION, "WREPL_START_ASSOCIATION"},
122 {WREPL_START_ASSOCIATION_REPLY, "WREPL_START_ASSOCIATION_REPLY"},
123 {WREPL_STOP_ASSOCIATION, "WREPL_STOP_ASSOCIATION"},
124 {WREPL_REPLICATION, "WREPL_REPLICATION"},
129 dissect_winsrepl_start(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
130 int winsrepl_offset, proto_tree *winsrepl_tree,
131 struct winsrepl_frame_data *winsrepl)
133 struct wrepl_start *start = &winsrepl->w.packet.message.start;
134 proto_item *start_item = NULL;
135 proto_tree *start_tree = NULL;
138 start_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WREPL_START_ASSOCIATION");
139 start_tree = proto_item_add_subtree(start_item, ett_winsrepl_start);
143 start->assoc_ctx = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
144 proto_tree_add_uint(start_tree, hf_winsrepl_assoc_ctx, winsrepl_tvb, winsrepl_offset, 4, start->assoc_ctx);
145 winsrepl_offset += 4;
148 start->minor_version = tvb_get_ntohs(winsrepl_tvb, winsrepl_offset);
149 proto_tree_add_uint(start_tree, hf_winsrepl_start_minor_version, winsrepl_tvb, winsrepl_offset, 2, start->minor_version);
150 winsrepl_offset += 2;
153 start->major_version = tvb_get_ntohs(winsrepl_tvb, winsrepl_offset);
154 proto_tree_add_uint(start_tree, hf_winsrepl_start_major_version, winsrepl_tvb, winsrepl_offset, 2, start->major_version);
155 winsrepl_offset += 2;
157 return winsrepl_offset;
161 dissect_winsrepl_stop(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
162 int winsrepl_offset, proto_tree *winsrepl_tree,
163 struct winsrepl_frame_data *winsrepl)
165 struct wrepl_stop *stop = &winsrepl->w.packet.message.stop;
166 proto_item *stop_item = NULL;
167 proto_tree *stop_tree = NULL;
170 stop_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WREPL_STOP_ASSOCIATION");
171 stop_tree = proto_item_add_subtree(stop_item, ett_winsrepl_stop);
175 stop->reason = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
176 proto_tree_add_uint(stop_tree, hf_winsrepl_stop_reason, winsrepl_tvb, winsrepl_offset, 4, stop->reason);
177 winsrepl_offset += 4;
179 return winsrepl_offset;
183 dissect_winsrepl_table_query(tvbuff_t *winsrepl_tvb _U_, packet_info *pinfo _U_,
184 int winsrepl_offset, proto_tree *winsrepl_tree _U_,
185 struct winsrepl_frame_data *winsrepl _U_)
187 /* Nothing to do here */
188 return winsrepl_offset;
192 dissect_winsrepl_wins_owner(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
193 int winsrepl_offset, proto_tree *winsrepl_tree,
194 _U_ struct winsrepl_frame_data *winsrepl,
195 struct wrepl_wins_owner *owner,
196 proto_tree *sub_tree,
199 proto_item *owner_item = NULL;
200 proto_tree *owner_tree = NULL;
201 const guint8 *addr_ptr;
205 owner_item = proto_tree_add_text(sub_tree, winsrepl_tvb, winsrepl_offset, 24 , "WINS Owner [%u]", index);
206 owner_tree = proto_item_add_subtree(owner_item, ett_winsrepl_owner);
207 } else if (winsrepl_tree) {
208 owner_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 24 , "WINS Owner");
209 owner_tree = proto_item_add_subtree(owner_item, ett_winsrepl_owner);
213 addr_ptr = tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
214 addr = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
215 SET_ADDRESS(&owner->address, AT_IPv4, 4, addr_ptr);
216 proto_tree_add_ipv4(owner_tree, hf_winsrepl_owner_address, winsrepl_tvb, winsrepl_offset, 4, addr);
217 winsrepl_offset += 4;
220 owner->max_version = tvb_get_ntoh64(winsrepl_tvb, winsrepl_offset);
221 proto_tree_add_uint64(owner_tree, hf_winsrepl_owner_max_version, winsrepl_tvb, winsrepl_offset, 8, owner->max_version);
222 winsrepl_offset += 8;
225 owner->min_version = tvb_get_ntoh64(winsrepl_tvb, winsrepl_offset);
226 proto_tree_add_uint64(owner_tree, hf_winsrepl_owner_min_version, winsrepl_tvb, winsrepl_offset, 8, owner->min_version);
227 winsrepl_offset += 8;
230 owner->type = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
231 proto_tree_add_uint(owner_tree, hf_winsrepl_owner_type, winsrepl_tvb, winsrepl_offset, 4, owner->type);
232 winsrepl_offset += 4;
234 return winsrepl_offset;
238 dissect_winsrepl_table_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
239 int winsrepl_offset, proto_tree *winsrepl_tree,
240 struct winsrepl_frame_data *winsrepl)
242 struct wrepl_table *table = &winsrepl->w.packet.message.replication.info.table;
243 struct wrepl_wins_owner owner;
244 proto_item *table_item = NULL;
245 proto_tree *table_tree = NULL;
246 const guint8 *initiator_ptr;
251 table_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WREPL_REPL_TABLE_REPLY");
252 table_tree = proto_item_add_subtree(table_item, ett_winsrepl_table_reply);
256 table->partner_count = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
257 proto_tree_add_uint(table_tree, hf_winsrepl_table_partner_count, winsrepl_tvb, winsrepl_offset, 4, table->partner_count);
258 winsrepl_offset += 4;
260 for (i=0; i < table->partner_count; i++) {
261 winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
262 winsrepl_offset, table_tree,
263 winsrepl, &owner, table_tree, i);
267 initiator_ptr= tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
268 initiator = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
269 SET_ADDRESS(&table->initiator, AT_IPv4, 4, initiator_ptr);
270 proto_tree_add_ipv4(table_tree, hf_winsrepl_table_initiator, winsrepl_tvb, winsrepl_offset, 4, initiator);
271 winsrepl_offset += 4;
273 return winsrepl_offset;
277 dissect_winsrepl_send_request(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
278 int winsrepl_offset, proto_tree *winsrepl_tree,
279 struct winsrepl_frame_data *winsrepl)
281 struct wrepl_wins_owner *owner = &winsrepl->w.packet.message.replication.info.owner;
283 winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
284 winsrepl_offset, winsrepl_tree,
285 winsrepl, owner, NULL, 0);
287 return winsrepl_offset;
291 dissect_winsrepl_wins_ip(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
292 int winsrepl_offset, proto_tree *winsrepl_tree,
293 _U_ struct winsrepl_frame_data *winsrepl,
295 proto_tree *sub_tree,
298 proto_item *ip_item = NULL;
299 proto_tree *ip_tree = NULL;
300 const guint8 *addr_ptr;
304 ip_item = proto_tree_add_text(sub_tree, winsrepl_tvb, winsrepl_offset, 8 , "WINS IP [%u]", index);
305 ip_tree = proto_item_add_subtree(ip_item, ett_winsrepl_ip);
306 } else if (winsrepl_tree) {
307 ip_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 8 , "WINS IP");
308 ip_tree = proto_item_add_subtree(ip_item, ett_winsrepl_ip);
312 addr_ptr= tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
313 addr = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
314 SET_ADDRESS(&ip->owner, AT_IPv4, 4, addr_ptr);
315 proto_tree_add_ipv4(ip_tree, hf_winsrepl_ip_owner, winsrepl_tvb, winsrepl_offset, 4, addr);
316 winsrepl_offset += 4;
319 addr_ptr= tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
320 addr = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
321 SET_ADDRESS(&ip->ip, AT_IPv4, 4, addr_ptr);
322 proto_tree_add_ipv4(ip_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, addr);
323 proto_item_append_text(ip_item, ": %s", ip_to_str(ip->ip.data));
324 winsrepl_offset += 4;
326 return winsrepl_offset;
330 dissect_winsrepl_wins_address_list(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
331 int winsrepl_offset, proto_tree *winsrepl_tree,
332 struct winsrepl_frame_data *winsrepl,
333 struct wrepl_address_list *addresses,
334 proto_item *parent_item)
336 proto_item *addr_list_item = NULL;
337 proto_tree *addr_list_tree = NULL;
338 int old_offset = winsrepl_offset;
343 addr_list_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WINS Address LIst");
344 addr_list_tree = proto_item_add_subtree(addr_list_item, ett_winsrepl_addr_list);
348 addresses->num_ips = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
349 proto_tree_add_uint(addr_list_tree, hf_winsrepl_addr_list_num_ips, winsrepl_tvb, winsrepl_offset, 4, addresses->num_ips);
350 winsrepl_offset += 4;
352 for (i=0; i < addresses->num_ips; i++) {
353 winsrepl_offset = dissect_winsrepl_wins_ip(winsrepl_tvb, pinfo,
354 winsrepl_offset, addr_list_tree,
355 winsrepl, &ip, addr_list_tree, i);
357 proto_item_append_text(parent_item, ": %s", ip_to_str(ip.ip.data));
358 proto_item_append_text(addr_list_item, ": %s", ip_to_str(ip.ip.data));
360 proto_item_append_text(parent_item, ", %s", ip_to_str(ip.ip.data));
361 proto_item_append_text(addr_list_item, ", %s", ip_to_str(ip.ip.data));
365 proto_item_set_len(addr_list_item, winsrepl_offset - old_offset);
367 return winsrepl_offset;
371 dissect_winsrepl_wins_name(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
372 int winsrepl_offset, proto_tree *winsrepl_tree,
373 struct winsrepl_frame_data *winsrepl,
374 struct wrepl_wins_name *name,
375 proto_tree *sub_tree,
378 proto_item *name_item = NULL;
379 proto_tree *name_tree = NULL;
380 int old_offset = winsrepl_offset;
381 tvbuff_t *name_tvb = NULL;
382 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
384 const guint8 *addr_ptr;
388 name_item = proto_tree_add_text(sub_tree, winsrepl_tvb, winsrepl_offset, -1 , "WINS Name [%u]", index);
389 name_tree = proto_item_add_subtree(name_item, ett_winsrepl_name);
390 } else if (winsrepl_tree) {
391 name_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WINS Name");
392 name_tree = proto_item_add_subtree(name_item, ett_winsrepl_name);
396 name->name_len = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
397 proto_tree_add_uint(name_tree, hf_winsrepl_name_len, winsrepl_tvb, winsrepl_offset, 4, name->name_len);
398 winsrepl_offset += 4;
401 name_tvb = tvb_new_subset(winsrepl_tvb, winsrepl_offset, name->name_len, name->name_len);
402 netbios_add_name("Name", name_tvb, 0, name_tree);
403 name_type = get_netbios_name(name_tvb, 0, name_str);
404 proto_item_append_text(name_item, ": %s<%02x>", name_str, name_type);
405 winsrepl_offset += name->name_len;
407 /* ALIGN to 4 Byte */
408 winsrepl_offset += ((winsrepl_offset & (4-1)) == 0 ? 0 : (4 - (winsrepl_offset & (4-1))));
411 name->flags = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
412 proto_tree_add_uint(name_tree, hf_winsrepl_name_flags, winsrepl_tvb, winsrepl_offset, 4, name->flags);
413 winsrepl_offset += 4;
416 name->group_flag = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
417 proto_tree_add_uint(name_tree, hf_winsrepl_name_group_flag, winsrepl_tvb, winsrepl_offset, 4, name->group_flag);
418 winsrepl_offset += 4;
421 name->id = tvb_get_ntoh64(winsrepl_tvb, winsrepl_offset);
422 proto_tree_add_uint64(name_tree, hf_winsrepl_name_id, winsrepl_tvb, winsrepl_offset, 8, name->id);
423 winsrepl_offset += 8;
425 switch (name->flags & 2) {
428 addr_ptr= tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
429 addr = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
430 SET_ADDRESS(&name->addresses.ip, AT_IPv4, 4, addr_ptr);
431 proto_tree_add_ipv4(name_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, addr);
432 proto_item_append_text(name_item, ": %s", ip_to_str(name->addresses.ip.data));
433 winsrepl_offset += 4;
436 winsrepl_offset = dissect_winsrepl_wins_address_list(winsrepl_tvb, pinfo,
437 winsrepl_offset, name_tree,
438 winsrepl, &name->addresses.addresses, name_item);
443 /* UNKNOWN, little or big endian??? */
444 addr_ptr= tvb_get_ptr(winsrepl_tvb, winsrepl_offset, 4);
445 addr = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
446 SET_ADDRESS(&name->unknown, AT_IPv4, 4, addr_ptr);
447 proto_tree_add_ipv4(name_tree, hf_winsrepl_name_unknown, winsrepl_tvb, winsrepl_offset, 4, addr);
448 winsrepl_offset += 4;
450 proto_item_set_len(name_item, winsrepl_offset - old_offset);
452 return winsrepl_offset;
456 dissect_winsrepl_send_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
457 int winsrepl_offset, proto_tree *winsrepl_tree,
458 struct winsrepl_frame_data *winsrepl)
460 struct wrepl_send_reply *reply = &winsrepl->w.packet.message.replication.info.reply;
461 struct wrepl_wins_name name;
462 proto_item *rep_item = NULL;
463 proto_tree *rep_tree = NULL;
467 rep_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WREPL_REPL_SEND_REPLY");
468 rep_tree = proto_item_add_subtree(rep_item, ett_winsrepl_send_reply);
472 reply->num_names = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
473 proto_tree_add_uint(rep_tree, hf_winsrepl_reply_num_names, winsrepl_tvb, winsrepl_offset, 4, reply->num_names);
474 winsrepl_offset += 4;
476 for (i=0; i < reply->num_names; i++) {
477 winsrepl_offset = dissect_winsrepl_wins_name(winsrepl_tvb, pinfo,
478 winsrepl_offset, rep_tree,
479 winsrepl, &name, rep_tree, i);
482 return winsrepl_offset;
486 dissect_winsrepl_update(tvbuff_t *winsrepl_tvb _U_, packet_info *pinfo _U_,
487 int winsrepl_offset, proto_tree *winsrepl_tree _U_,
488 struct winsrepl_frame_data *winsrepl _U_)
490 return winsrepl_offset;
494 dissect_winsrepl_inform(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
495 int winsrepl_offset, proto_tree *winsrepl_tree,
496 struct winsrepl_frame_data *winsrepl)
498 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
499 winsrepl_offset, winsrepl_tree,
501 return winsrepl_offset;
505 dissect_winsrepl_5_or_9(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
506 int winsrepl_offset, proto_tree *winsrepl_tree,
507 struct winsrepl_frame_data *winsrepl)
509 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
510 winsrepl_offset, winsrepl_tree,
512 return winsrepl_offset;
516 dissect_winsrepl_replication(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
517 int winsrepl_offset, proto_tree *winsrepl_tree,
518 struct winsrepl_frame_data *winsrepl)
520 struct wrepl_replication *repl = &winsrepl->w.packet.message.replication;
521 proto_item *repl_item = NULL;
522 proto_tree *repl_tree = NULL;
525 repl_item = proto_tree_add_text(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1 , "WREPL_REPLICATION");
526 repl_tree = proto_item_add_subtree(repl_item, ett_winsrepl_replication);
529 /* REPLIICATION_CMD */
530 repl->command = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
531 proto_tree_add_uint(repl_tree, hf_winsrepl_replication_command, winsrepl_tvb, winsrepl_offset, 4, repl->command);
532 winsrepl_offset += 4;
534 switch (repl->command) {
535 case WREPL_REPL_TABLE_QUERY:
536 winsrepl_offset = dissect_winsrepl_table_query(winsrepl_tvb, pinfo,
537 winsrepl_offset, repl_tree,
540 case WREPL_REPL_TABLE_REPLY:
541 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
542 winsrepl_offset, repl_tree,
545 case WREPL_REPL_SEND_REQUEST:
546 winsrepl_offset = dissect_winsrepl_send_request(winsrepl_tvb, pinfo,
547 winsrepl_offset, repl_tree,
550 case WREPL_REPL_SEND_REPLY:
551 winsrepl_offset = dissect_winsrepl_send_reply(winsrepl_tvb, pinfo,
552 winsrepl_offset, repl_tree,
555 case WREPL_REPL_UPDATE:
556 winsrepl_offset = dissect_winsrepl_update(winsrepl_tvb, pinfo,
557 winsrepl_offset, repl_tree,
562 winsrepl_offset = dissect_winsrepl_5_or_9(winsrepl_tvb, pinfo,
563 winsrepl_offset, repl_tree,
566 case WREPL_REPL_INFORM:
567 winsrepl_offset = dissect_winsrepl_inform(winsrepl_tvb, pinfo,
568 winsrepl_offset, repl_tree,
573 return winsrepl_offset;
577 dissect_winsrepl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
579 int winsrepl_offset = 0;
580 tvbuff_t *winsrepl_tvb = NULL;
581 proto_item *winsrepl_item = NULL;
582 proto_tree *winsrepl_tree = NULL;
583 struct winsrepl_frame_data _winsrepl_frame;
584 struct winsrepl_frame_data *winsrepl = &_winsrepl_frame;
586 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
587 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WINS-Replication");
589 if (check_col(pinfo->cinfo, COL_INFO)){
590 col_clear(pinfo->cinfo, COL_INFO);
593 winsrepl_tvb = tvb_new_subset(tvb, 0, -1, -1);
596 winsrepl_item = proto_tree_add_item(parent_tree, proto_winsrepl, winsrepl_tvb, winsrepl_offset, -1, FALSE);
597 winsrepl_tree = proto_item_add_subtree(winsrepl_item, ett_winsrepl);
601 winsrepl->w.size = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
602 proto_tree_add_uint(winsrepl_tree, hf_winsrepl_size, winsrepl_tvb, winsrepl_offset, 4, winsrepl->w.size);
603 winsrepl_offset += 4;
605 proto_item_set_len(winsrepl_item, winsrepl->w.size + 4);
608 winsrepl->w.packet.opcode = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
609 proto_tree_add_uint(winsrepl_tree, hf_winsrepl_opcode, winsrepl_tvb, winsrepl_offset, 4, winsrepl->w.packet.opcode);
610 winsrepl_offset += 4;
613 winsrepl->w.packet.assoc_ctx = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
614 proto_tree_add_uint(winsrepl_tree, hf_winsrepl_assoc_ctx, winsrepl_tvb, winsrepl_offset, 4, winsrepl->w.packet.assoc_ctx);
615 winsrepl_offset += 4;
618 winsrepl->w.packet.mess_type = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
619 proto_tree_add_uint(winsrepl_tree, hf_winsrepl_mess_type, winsrepl_tvb, winsrepl_offset, 4, winsrepl->w.packet.mess_type);
620 winsrepl_offset += 4;
622 switch (winsrepl->w.packet.mess_type) {
623 case WREPL_START_ASSOCIATION:
624 winsrepl_offset = dissect_winsrepl_start(winsrepl_tvb, pinfo,
625 winsrepl_offset, winsrepl_tree,
628 case WREPL_START_ASSOCIATION_REPLY:
629 winsrepl_offset = dissect_winsrepl_start(winsrepl_tvb, pinfo,
630 winsrepl_offset, winsrepl_tree,
633 case WREPL_STOP_ASSOCIATION:
634 winsrepl_offset = dissect_winsrepl_stop(winsrepl_tvb, pinfo,
635 winsrepl_offset, winsrepl_tree,
638 case WREPL_REPLICATION:
639 winsrepl_offset = dissect_winsrepl_replication(winsrepl_tvb, pinfo,
640 winsrepl_offset, winsrepl_tree,
649 dissect_winsrepl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
653 if (!winsrepl_reassemble || !pinfo->can_desegment) {
654 dissect_winsrepl_pdu(tvb, pinfo, parent_tree);
658 while (tvb_reported_length_remaining(tvb, offset) > 0) {
659 guint length_remaining = 0;
660 tvbuff_t *pdu_tvb = NULL;
661 guint32 pdu_size = 0;
663 length_remaining = tvb_ensure_length_remaining(tvb, offset);
664 if (length_remaining < 4) {
665 pinfo->desegment_offset = offset;
666 pinfo->desegment_len = 4 - length_remaining;
670 pdu_size = tvb_get_ntohl(tvb, offset);
673 if (length_remaining < pdu_size) {
674 pinfo->want_pdu_tracking = 2;
675 pinfo->bytes_until_next_pdu = pdu_size - length_remaining;
676 pinfo->desegment_offset = offset;
677 pinfo->desegment_len = pdu_size - length_remaining;
681 pdu_tvb = tvb_new_subset(tvb, offset, pdu_size, pdu_size);
683 dissect_winsrepl_pdu(pdu_tvb, pinfo, parent_tree);
692 proto_register_winsrepl(void)
694 static hf_register_info hf[] = {
695 { &hf_winsrepl_size, {
696 "Packet Size", "winsrepl.size",
697 FT_UINT32, BASE_DEC, NULL, 0x0,
698 "WINS Replication Packet Size", HFILL }},
700 { &hf_winsrepl_opcode, {
701 "Opcode", "winsrepl.opcode",
702 FT_UINT32, BASE_HEX, NULL, 0x0,
703 "WINS Replication Opcode", HFILL }},
705 { &hf_winsrepl_assoc_ctx, {
706 "Assoc_Ctx", "winsrepl.assoc_ctx",
707 FT_UINT32, BASE_HEX, NULL, 0x0,
708 "WINS Replication Assoc_Ctx", HFILL }},
710 { &hf_winsrepl_mess_type, {
711 "Assoc_Ctx", "winsrepl.message_type",
712 FT_UINT32, BASE_DEC, VALS(message_type_vals), 0x0,
713 "WINS Replication Message_Type", HFILL }},
715 { &hf_winsrepl_start_minor_version, {
716 "Minor Version", "winsrepl.minor_version",
717 FT_UINT16, BASE_DEC, NULL, 0x0,
718 "WINS Replication Minor Version", HFILL }},
720 { &hf_winsrepl_start_major_version, {
721 "Major Version", "winsrepl.major_version",
722 FT_UINT16, BASE_DEC, NULL, 0x0,
723 "WINS Replication Major Version", HFILL }},
725 { &hf_winsrepl_stop_reason, {
726 "Reason", "winsrepl.reason",
727 FT_UINT32, BASE_HEX, NULL, 0x0,
728 "WINS Replication Reason", HFILL }},
730 { &hf_winsrepl_replication_command, {
731 "Replication Command", "winsrepl.repl_cmd",
732 FT_UINT32, BASE_HEX, VALS(replication_cmd_vals), 0x0,
733 "WINS Replication Command", HFILL }},
735 { &hf_winsrepl_owner_address, {
736 "Owner Address", "winsrepl.owner_address",
737 FT_IPv4, BASE_NONE, NULL, 0x0,
738 "WINS Replication Owner Address", HFILL }},
740 { &hf_winsrepl_owner_max_version, {
741 "Max Version", "winsrepl.max_version",
742 FT_UINT64, BASE_DEC, NULL, 0x0,
743 "WINS Replication Max Version", HFILL }},
745 { &hf_winsrepl_owner_min_version, {
746 "Min Version", "winsrepl.min_version",
747 FT_UINT64, BASE_DEC, NULL, 0x0,
748 "WINS Replication Min Version", HFILL }},
750 { &hf_winsrepl_owner_type, {
751 "Owner Type", "winsrepl.owner_type",
752 FT_UINT32, BASE_DEC, NULL, 0x0,
753 "WINS Replication Owner Type", HFILL }},
755 { &hf_winsrepl_table_partner_count, {
756 "Partner Count", "winsrepl.partner_count",
757 FT_UINT32, BASE_DEC, NULL, 0x0,
758 "WINS Replication Partner Count", HFILL }},
760 { &hf_winsrepl_table_initiator, {
761 "Initiator", "winsrepl.initiator",
762 FT_IPv4, BASE_NONE, NULL, 0x0,
763 "WINS Replication Initiator", HFILL }},
765 { &hf_winsrepl_ip_owner, {
766 "IP Owner", "winsrepl.ip_owner",
767 FT_IPv4, BASE_NONE, NULL, 0x0,
768 "WINS Replication IP Owner", HFILL }},
770 { &hf_winsrepl_ip_ip, {
771 "IP Address", "winsrepl.ip_address",
772 FT_IPv4, BASE_NONE, NULL, 0x0,
773 "WINS Replication IP Address", HFILL }},
775 { &hf_winsrepl_addr_list_num_ips, {
776 "Num IPs", "winsrepl.num_ips",
777 FT_UINT32, BASE_DEC, NULL, 0x0,
778 "WINS Replication Num IPs", HFILL }},
780 { &hf_winsrepl_name_len, {
781 "Name Len", "winsrepl.name_len",
782 FT_UINT32, BASE_DEC, NULL, 0x0,
783 "WINS Replication Name Len", HFILL }},
785 { &hf_winsrepl_name_flags, {
786 "Name Flags", "winsrepl.name_flags",
787 FT_UINT32, BASE_HEX, NULL, 0x0,
788 "WINS Replication Name Flags", HFILL }},
790 { &hf_winsrepl_name_group_flag, {
791 "Name Group Flag", "winsrepl.name_group_flag",
792 FT_UINT32, BASE_HEX, NULL, 0x0,
793 "WINS Replication Name Group Flag", HFILL }},
795 { &hf_winsrepl_name_id, {
796 "Name Id", "winsrepl.name_id",
797 FT_UINT64, BASE_DEC, NULL, 0x0,
798 "WINS Replication Name Id", HFILL }},
800 { &hf_winsrepl_name_unknown, {
801 "Unknown IP", "winsrepl.unknown",
802 FT_IPv4, BASE_NONE, NULL, 0x0,
803 "WINS Replication Unknown IP", HFILL }},
805 { &hf_winsrepl_reply_num_names, {
806 "Num Names", "winsrepl.num_names",
807 FT_UINT32, BASE_DEC, NULL, 0x0,
808 "WINS Replication Num Names", HFILL }},
811 static gint *ett[] = {
815 &ett_winsrepl_replication,
817 &ett_winsrepl_table_reply,
819 &ett_winsrepl_addr_list,
821 &ett_winsrepl_send_reply,
824 module_t *winsrepl_module;
826 proto_winsrepl = proto_register_protocol("WINS (Windows Internet Name Service) Replication",
827 "WINS-Replication", "winsrepl");
828 proto_register_subtree_array(ett, array_length(ett));
829 proto_register_field_array(proto_winsrepl, hf, array_length(hf));
831 winsrepl_module = prefs_register_protocol(proto_winsrepl, NULL);
832 prefs_register_bool_preference(winsrepl_module, "reassemble",
833 "Reassemble WINS-Replication messages spanning multiple TCP segments",
834 "Whether the WINS-Replication dissector should reassemble messages spanning multiple TCP segments."
835 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
836 &winsrepl_reassemble);
840 proto_reg_handoff_winsrepl(void)
842 winsrepl_handle = create_dissector_handle(dissect_winsrepl, proto_winsrepl);
843 dissector_add("tcp.port", glb_winsrepl_tcp_port, winsrepl_handle);