Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-winsrepl.c
blobb0517a0ffefb27a9df12c29238c2620149f04bc6
1 /*
2 * packet-winsrepl.c
4 * Routines for WINS Replication packet dissection
6 * Copyright 2005 Stefan Metzmacher <metze@samba.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/exceptions.h>
20 #include <epan/prefs.h>
21 #include <epan/to_str.h>
23 #include "packet-netbios.h"
25 #include "packet-tcp.h"
27 void proto_register_winsrepl(void);
28 void proto_reg_handoff_winsrepl(void);
29 static dissector_handle_t winsrepl_handle;
31 static bool winsrepl_reassemble = true;
33 static int proto_winsrepl;
35 static int hf_winsrepl_size;
36 static int hf_winsrepl_opcode;
37 static int hf_winsrepl_assoc_ctx;
38 static int hf_winsrepl_mess_type;
40 static int hf_winsrepl_start_minor_version;
41 static int hf_winsrepl_start_major_version;
43 static int hf_winsrepl_stop_reason;
45 static int hf_winsrepl_replication_command;
47 static int hf_winsrepl_owner_address;
48 static int hf_winsrepl_owner_max_version;
49 static int hf_winsrepl_owner_min_version;
50 static int hf_winsrepl_owner_type;
52 static int hf_winsrepl_table_partner_count;
53 static int hf_winsrepl_table_initiator;
55 static int hf_winsrepl_ip_owner;
56 static int hf_winsrepl_ip_ip;
57 static int hf_winsrepl_addr_list_num_ips;
59 static int hf_winsrepl_name_len;
60 static int hf_winsrepl_name_flags;
61 static int hf_winsrepl_name_flags_rectype;
62 static int hf_winsrepl_name_flags_recstate;
63 static int hf_winsrepl_name_flags_local;
64 static int hf_winsrepl_name_flags_hosttype;
65 static int hf_winsrepl_name_flags_static;
66 static int hf_winsrepl_name_group_flag;
67 static int hf_winsrepl_name_version_id;
68 static int hf_winsrepl_name_unknown;
70 static int hf_winsrepl_reply_num_names;
72 static int ett_winsrepl;
74 static int ett_winsrepl_start;
75 static int ett_winsrepl_stop;
76 static int ett_winsrepl_replication;
78 static int ett_winsrepl_owner;
79 static int ett_winsrepl_table_reply;
81 static int ett_winsrepl_ip;
82 static int ett_winsrepl_addr_list;
84 static int ett_winsrepl_name;
85 static int ett_winsrepl_send_reply;
87 static int ett_winsrepl_flags;
89 static expert_field ei_winsrepl_name_len;
91 #define WINS_REPLICATION_PORT ( 42 )
92 #define WREPL_OPCODE_BITS ( 0x7800 )
94 enum wrepl_replication_cmd {
95 WREPL_REPL_TABLE_QUERY=0,
96 WREPL_REPL_TABLE_REPLY=1,
97 WREPL_REPL_SEND_REQUEST=2,
98 WREPL_REPL_SEND_REPLY=3,
99 WREPL_REPL_UPDATE=4,
100 WREPL_REPL_UPDATE2=5,
101 WREPL_REPL_INFORM=8,
102 WREPL_REPL_INFORM2=9
105 enum wrepl_mess_type {
106 WREPL_START_ASSOCIATION=0,
107 WREPL_START_ASSOCIATION_REPLY=1,
108 WREPL_STOP_ASSOCIATION=2,
109 WREPL_REPLICATION=3
112 static const value_string replication_cmd_vals[] = {
113 {WREPL_REPL_TABLE_QUERY, "WREPL_REPL_TABLE_QUERY"},
114 {WREPL_REPL_TABLE_REPLY, "WREPL_REPL_TABLE_REPLY"},
115 {WREPL_REPL_SEND_REQUEST, "WREPL_REPL_SEND_REQUEST"},
116 {WREPL_REPL_SEND_REPLY, "WREPL_REPL_SEND_REPLY"},
117 {WREPL_REPL_UPDATE, "WREPL_REPL_UPDATE"},
118 {WREPL_REPL_UPDATE2, "WREPL_REPL_UPDATE2"},
119 {WREPL_REPL_INFORM, "WREPL_REPL_INFORM"},
120 {WREPL_REPL_INFORM2, "WREPL_REPL_INFORM2"},
121 {0, NULL}
124 static const value_string message_type_vals[] = {
125 {WREPL_START_ASSOCIATION, "WREPL_START_ASSOCIATION"},
126 {WREPL_START_ASSOCIATION_REPLY, "WREPL_START_ASSOCIATION_REPLY"},
127 {WREPL_STOP_ASSOCIATION, "WREPL_STOP_ASSOCIATION"},
128 {WREPL_REPLICATION, "WREPL_REPLICATION"},
129 {0, NULL}
132 #define WREPL_NAME_TYPE_MASK 0x03
134 #define WREPL_NAME_TYPE_UNIQUE 0x00
135 #define WREPL_NAME_TYPE_NORMAL_GROUP 0x01
136 #define WREPL_NAME_TYPE_SPECIAL_GROUP 0x02
137 #define WREPL_NAME_TYPE_MULTIHOMED 0x03
139 static const value_string rectype_vals[] = {
140 {WREPL_NAME_TYPE_UNIQUE, "Unique"},
141 {WREPL_NAME_TYPE_NORMAL_GROUP, "Normal group"},
142 {WREPL_NAME_TYPE_SPECIAL_GROUP, "Special group"},
143 {WREPL_NAME_TYPE_MULTIHOMED, "Multihomed"},
144 {0, NULL}
147 static const value_string recstate_vals[] = {
148 {0x00, "Active"},
149 {0x01, "Released"},
150 {0x02, "Tombstoned"},
151 {0x03, "Deleted"},
152 {0, NULL}
155 static const value_string hosttype_vals[] = {
156 {0x00, "B-node"},
157 {0x01, "P-node"},
158 {0x02, "M-node"},
159 {0x03, "H-node"},
160 {0, NULL}
163 static int
164 dissect_winsrepl_start(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
165 int winsrepl_offset, proto_tree *winsrepl_tree)
167 proto_tree *start_tree;
169 start_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
170 ett_winsrepl_start, NULL, "WREPL_START_ASSOCIATION");
172 /* ASSOC_CTX */
173 proto_tree_add_item(start_tree, hf_winsrepl_assoc_ctx, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
174 winsrepl_offset += 4;
176 /* MINOR VERSION */
177 proto_tree_add_item(start_tree, hf_winsrepl_start_minor_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
178 winsrepl_offset += 2;
180 /* MAJOR VERSION */
181 proto_tree_add_item(start_tree, hf_winsrepl_start_major_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
182 winsrepl_offset += 2;
184 return winsrepl_offset;
187 static int
188 dissect_winsrepl_stop(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
189 int winsrepl_offset, proto_tree *winsrepl_tree)
191 uint32_t reason;
192 proto_item *stop_item;
193 proto_tree *stop_tree;
195 stop_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
196 ett_winsrepl_stop, &stop_item, "WREPL_STOP_ASSOCIATION");
198 /* REASON */
199 reason = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
200 proto_tree_add_uint(stop_tree, hf_winsrepl_stop_reason, winsrepl_tvb, winsrepl_offset, 4, reason);
201 winsrepl_offset += 4;
203 proto_item_append_text(stop_item, ", Reason: 0x%08X", reason);
205 return winsrepl_offset;
208 static int
209 dissect_winsrepl_table_query(tvbuff_t *winsrepl_tvb _U_, packet_info *pinfo _U_,
210 int winsrepl_offset, proto_tree *winsrepl_tree _U_)
212 /* Nothing to do here */
213 return winsrepl_offset;
216 static int
217 dissect_winsrepl_wins_owner(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
218 int winsrepl_offset, proto_tree *winsrepl_tree,
219 proto_tree *sub_tree, uint32_t idx)
221 proto_tree *owner_tree = NULL;
223 if (sub_tree) {
224 owner_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 24,
225 ett_winsrepl_owner, NULL, "WINS Owner [%u]", idx);
226 } else if (winsrepl_tree) {
227 owner_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 24,
228 ett_winsrepl_owner, NULL, "WINS Owner");
231 /* ADDRESS */
232 proto_tree_add_item(owner_tree, hf_winsrepl_owner_address, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
233 winsrepl_offset += 4;
235 /* MAX_VERSION */
236 proto_tree_add_item(owner_tree, hf_winsrepl_owner_max_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
237 winsrepl_offset += 8;
239 /* MIN_VERSION */
240 proto_tree_add_item(owner_tree, hf_winsrepl_owner_min_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
241 winsrepl_offset += 8;
243 /* TYPE */
244 proto_tree_add_item(owner_tree, hf_winsrepl_owner_type, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
245 winsrepl_offset += 4;
247 return winsrepl_offset;
250 static int
251 dissect_winsrepl_table_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
252 int winsrepl_offset, proto_tree *winsrepl_tree)
254 proto_tree *table_tree;
255 uint32_t partner_count;
256 uint32_t i;
258 table_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
259 ett_winsrepl_table_reply, NULL, "WREPL_REPL_TABLE_REPLY");
261 /* PARTNER COUNT */
262 partner_count = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
263 proto_tree_add_uint(table_tree, hf_winsrepl_table_partner_count, winsrepl_tvb, winsrepl_offset, 4, partner_count);
264 winsrepl_offset += 4;
266 for (i=0; i < partner_count; i++) {
267 winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
268 winsrepl_offset, table_tree,
269 table_tree, i);
272 /* INITIATOR */
273 proto_tree_add_item(table_tree, hf_winsrepl_table_initiator, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
274 winsrepl_offset += 4;
276 return winsrepl_offset;
279 static int
280 dissect_winsrepl_send_request(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
281 int winsrepl_offset, proto_tree *winsrepl_tree)
283 winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
284 winsrepl_offset, winsrepl_tree,
285 NULL, 0);
287 return winsrepl_offset;
290 static int
291 dissect_winsrepl_wins_ip(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
292 int winsrepl_offset, proto_tree *winsrepl_tree,
293 uint32_t *addr, proto_tree *sub_tree, uint32_t idx)
295 proto_item *ip_item = NULL;
296 proto_tree *ip_tree = NULL;
298 if (sub_tree) {
299 ip_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 8,
300 ett_winsrepl_ip, &ip_item, "WINS IP [%u]", idx);
301 } else if (winsrepl_tree) {
302 ip_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 8,
303 ett_winsrepl_ip, &ip_item, "WINS IP");
306 /* OWNER */
307 proto_tree_add_item(ip_tree, hf_winsrepl_ip_owner, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
308 winsrepl_offset += 4;
310 /* IP */
311 *addr = tvb_get_ipv4(winsrepl_tvb, winsrepl_offset);
312 proto_tree_add_ipv4(ip_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, *addr);
313 proto_item_append_text(ip_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
314 winsrepl_offset += 4;
316 return winsrepl_offset;
319 static int
320 dissect_winsrepl_wins_address_list(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
321 int winsrepl_offset, proto_tree *winsrepl_tree,
322 proto_item *parent_item)
324 proto_item *addr_list_item;
325 proto_tree *addr_list_tree;
326 int old_offset = winsrepl_offset;
327 uint32_t num_ips;
328 uint32_t ip;
329 uint32_t i;
330 address addr;
331 char* addr_str;
333 addr_list_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
334 ett_winsrepl_addr_list, &addr_list_item, "WINS Address List");
336 /* NUM_IPS */
337 num_ips = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
338 proto_tree_add_uint(addr_list_tree, hf_winsrepl_addr_list_num_ips, winsrepl_tvb, winsrepl_offset, 4, num_ips);
339 winsrepl_offset += 4;
341 for (i=0; i < num_ips; i++) {
342 winsrepl_offset = dissect_winsrepl_wins_ip(winsrepl_tvb, pinfo,
343 winsrepl_offset, addr_list_tree,
344 &ip, addr_list_tree, i);
345 set_address(&addr, AT_IPv4, 4, &ip);
346 addr_str = address_to_str(pinfo->pool, &addr);
347 if (i == 0) {
348 proto_item_append_text(parent_item, ": %s", addr_str);
349 proto_item_append_text(addr_list_item, ": %s", addr_str);
350 } else {
351 proto_item_append_text(parent_item, ", %s", addr_str);
352 proto_item_append_text(addr_list_item, ", %s", addr_str);
356 proto_item_set_len(addr_list_item, winsrepl_offset - old_offset);
358 return winsrepl_offset;
361 static int
362 dissect_winsrepl_wins_name(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
363 int winsrepl_offset, proto_tree *winsrepl_tree,
364 proto_tree *sub_tree, uint32_t idx)
366 proto_item *name_item = NULL, *ti;
367 proto_tree *name_tree = NULL;
368 int old_offset = winsrepl_offset;
369 tvbuff_t *name_tvb = NULL;
370 uint32_t name_len;
371 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
372 int name_type;
373 uint32_t flags;
374 static int * const name_flags[] = {
375 &hf_winsrepl_name_flags_rectype,
376 &hf_winsrepl_name_flags_recstate,
377 &hf_winsrepl_name_flags_local,
378 &hf_winsrepl_name_flags_hosttype,
379 &hf_winsrepl_name_flags_static,
380 NULL
383 if (sub_tree) {
384 name_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, -1,
385 ett_winsrepl_name, &name_item, "WINS Name [%u]", idx);
386 } else if (winsrepl_tree) {
387 name_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
388 ett_winsrepl_name, &name_item, "WINS Name");
391 /* NAME_LEN */
392 name_len = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
393 ti = proto_tree_add_uint(name_tree, hf_winsrepl_name_len, winsrepl_tvb, winsrepl_offset, 4, name_len);
394 winsrepl_offset += 4;
395 if (name_len == 0) {
396 expert_add_info(pinfo, ti, &ei_winsrepl_name_len);
397 return winsrepl_offset;
400 /* NAME: TODO! */
402 * XXX - apparently, according to the Samba code for handling
403 * WINS replication, there's a bug in a lot of versions of Windows,
404 * including W2K SP2, wherein the first and last bytes of the
405 * name (the last byte being the name type) are swapped if
406 * the type is 0x1b. I think I've seen this in at least
407 * one capture.
409 name_tvb = tvb_new_subset_length(winsrepl_tvb, winsrepl_offset, name_len);
410 netbios_add_name("Name", name_tvb, 0, name_tree);
411 name_type = get_netbios_name(name_tvb, 0, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
412 proto_item_append_text(name_item, ": %s<%02x>", name_str, name_type);
413 winsrepl_offset += name_len;
415 /* ALIGN to 4 Byte */
416 /* winsrepl_offset += ((winsrepl_offset & (4-1)) == 0 ? 0 : (4 - (winsrepl_offset & (4-1)))); */
417 /* Windows including w2k8 add 4 padding bytes, when it's already 4 byte
418 * aligned... This happens when the name has a "scope" part
420 winsrepl_offset += 4 - (winsrepl_offset & (4-1));
422 /* FLAGS */
424 * XXX - there appear to be more flag bits, but I didn't see
425 * anything in the Samba code about them.
427 flags = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
428 proto_tree_add_bitmask(name_tree, winsrepl_tvb, winsrepl_offset, hf_winsrepl_name_flags, ett_winsrepl_flags, name_flags, ENC_BIG_ENDIAN);
429 winsrepl_offset += 4;
431 /* GROUP_FLAG */
432 /* XXX - is this just a Boolean? */
433 proto_tree_add_item(name_tree, hf_winsrepl_name_group_flag, winsrepl_tvb, winsrepl_offset, 4, ENC_LITTLE_ENDIAN);
434 winsrepl_offset += 4;
436 /* Version ID */
437 proto_tree_add_item(name_tree, hf_winsrepl_name_version_id, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
438 winsrepl_offset += 8;
440 switch (flags & WREPL_NAME_TYPE_MASK) {
442 case WREPL_NAME_TYPE_UNIQUE:
443 case WREPL_NAME_TYPE_NORMAL_GROUP:
444 /* Single address */
445 proto_tree_add_item(name_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
446 proto_item_append_text(name_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
447 winsrepl_offset += 4;
448 break;
450 case WREPL_NAME_TYPE_SPECIAL_GROUP:
451 case WREPL_NAME_TYPE_MULTIHOMED:
452 /* Address list */
453 winsrepl_offset = dissect_winsrepl_wins_address_list(winsrepl_tvb, pinfo,
454 winsrepl_offset, name_tree,
455 name_item);
456 break;
459 /* UNKNOWN, little or big endian??? */
460 proto_tree_add_item(name_tree, hf_winsrepl_name_unknown, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
461 winsrepl_offset += 4;
463 proto_item_set_len(name_item, winsrepl_offset - old_offset);
465 return winsrepl_offset;
468 static int
469 dissect_winsrepl_send_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
470 int winsrepl_offset, proto_tree *winsrepl_tree)
472 proto_tree *rep_tree;
473 uint32_t num_names;
474 uint32_t i;
476 rep_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
477 ett_winsrepl_send_reply, NULL, "WREPL_REPL_SEND_REPLY");
479 /* NUM NAMES */
480 num_names = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
481 proto_tree_add_uint(rep_tree, hf_winsrepl_reply_num_names, winsrepl_tvb, winsrepl_offset, 4, num_names);
482 winsrepl_offset += 4;
484 for (i=0; i < num_names; i++) {
485 winsrepl_offset = dissect_winsrepl_wins_name(winsrepl_tvb, pinfo,
486 winsrepl_offset, rep_tree,
487 rep_tree, i);
490 return winsrepl_offset;
493 static int
494 dissect_winsrepl_update(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
495 int winsrepl_offset, proto_tree *winsrepl_tree)
497 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
498 winsrepl_offset, winsrepl_tree);
499 return winsrepl_offset;
502 static int
503 dissect_winsrepl_update2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
504 int winsrepl_offset, proto_tree *winsrepl_tree)
506 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
507 winsrepl_offset, winsrepl_tree);
508 return winsrepl_offset;
511 static int
512 dissect_winsrepl_inform(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
513 int winsrepl_offset, proto_tree *winsrepl_tree)
515 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
516 winsrepl_offset, winsrepl_tree);
517 return winsrepl_offset;
520 static int
521 dissect_winsrepl_inform2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
522 int winsrepl_offset, proto_tree *winsrepl_tree)
524 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
525 winsrepl_offset, winsrepl_tree);
526 return winsrepl_offset;
529 static int
530 dissect_winsrepl_replication(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
531 int winsrepl_offset, proto_item *winsrepl_item, proto_tree *winsrepl_tree)
533 proto_item *repl_item;
534 proto_tree *repl_tree;
535 enum wrepl_replication_cmd command;
537 repl_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
538 ett_winsrepl_replication, &repl_item, "WREPL_REPLICATION");
540 /* REPLICATION_CMD */
541 command = (enum wrepl_replication_cmd)tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
542 proto_tree_add_uint(repl_tree, hf_winsrepl_replication_command, winsrepl_tvb, winsrepl_offset, 4, command);
543 winsrepl_offset += 4;
545 switch (command) {
546 case WREPL_REPL_TABLE_QUERY:
547 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_QUERY");
548 proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_QUERY");
549 proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_QUERY");
550 winsrepl_offset = dissect_winsrepl_table_query(winsrepl_tvb, pinfo,
551 winsrepl_offset, repl_tree);
552 break;
553 case WREPL_REPL_TABLE_REPLY:
554 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_REPLY");
555 proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_REPLY");
556 proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_REPLY");
557 winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
558 winsrepl_offset, repl_tree);
559 break;
560 case WREPL_REPL_SEND_REQUEST:
561 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REQUEST");
562 proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REQUEST");
563 proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REQUEST");
564 winsrepl_offset = dissect_winsrepl_send_request(winsrepl_tvb, pinfo,
565 winsrepl_offset, repl_tree);
566 break;
567 case WREPL_REPL_SEND_REPLY:
568 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REPLY");
569 proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REPLY");
570 proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REPLY");
571 winsrepl_offset = dissect_winsrepl_send_reply(winsrepl_tvb, pinfo,
572 winsrepl_offset, repl_tree);
573 break;
574 case WREPL_REPL_UPDATE:
575 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE");
576 proto_item_append_text(winsrepl_item, ", WREPL_REPL_UPDATE");
577 proto_item_append_text(repl_item, ", WREPL_REPL_UPDATE");
578 winsrepl_offset = dissect_winsrepl_update(winsrepl_tvb, pinfo,
579 winsrepl_offset, repl_tree);
580 break;
581 case WREPL_REPL_UPDATE2:
582 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE2");
583 proto_item_append_text(winsrepl_item, ",WREPL_REPL_UPDATE2");
584 proto_item_append_text(repl_item, ",WREPL_REPL_UPDATE2");
585 winsrepl_offset = dissect_winsrepl_update2(winsrepl_tvb, pinfo,
586 winsrepl_offset, repl_tree);
587 break;
588 case WREPL_REPL_INFORM:
589 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM");
590 proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM");
591 proto_item_append_text(repl_item, ", WREPL_REPL_INFORM");
592 winsrepl_offset = dissect_winsrepl_inform(winsrepl_tvb, pinfo,
593 winsrepl_offset, repl_tree);
594 break;
595 case WREPL_REPL_INFORM2:
596 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM2");
597 proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM2");
598 proto_item_append_text(repl_item, ", WREPL_REPL_INFORM2");
599 winsrepl_offset = dissect_winsrepl_inform2(winsrepl_tvb, pinfo,
600 winsrepl_offset, repl_tree);
601 break;
604 return winsrepl_offset;
607 static int
608 dissect_winsrepl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
610 int offset = 0;
611 proto_item *winsrepl_item;
612 proto_tree *winsrepl_tree;
613 enum wrepl_mess_type mess_type;
615 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WINS-Replication");
616 col_clear(pinfo->cinfo, COL_INFO);
618 winsrepl_item = proto_tree_add_item(parent_tree, proto_winsrepl, tvb, offset, -1, ENC_NA);
619 winsrepl_tree = proto_item_add_subtree(winsrepl_item, ett_winsrepl);
621 /* SIZE */
622 proto_tree_add_item(winsrepl_tree, hf_winsrepl_size, tvb, offset, 4, ENC_BIG_ENDIAN);
623 offset += 4;
625 /* OPCODE */
626 proto_tree_add_item(winsrepl_tree, hf_winsrepl_opcode, tvb, offset, 4, ENC_BIG_ENDIAN);
627 offset += 4;
629 /* ASSOC_CTX */
630 proto_tree_add_item(winsrepl_tree, hf_winsrepl_assoc_ctx, tvb, offset, 4, ENC_BIG_ENDIAN);
631 offset += 4;
633 /* MESSAGE_TYPE */
634 mess_type = (enum wrepl_mess_type)tvb_get_ntohl(tvb, offset);
635 proto_tree_add_uint(winsrepl_tree, hf_winsrepl_mess_type, tvb, offset, 4, mess_type);
636 offset += 4;
638 switch (mess_type) {
639 case WREPL_START_ASSOCIATION:
640 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION");
641 proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION");
642 dissect_winsrepl_start(tvb, pinfo,
643 offset, winsrepl_tree);
644 break;
645 case WREPL_START_ASSOCIATION_REPLY:
646 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION_REPLY");
647 proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION_REPLY");
648 dissect_winsrepl_start(tvb, pinfo,
649 offset, winsrepl_tree);
650 break;
651 case WREPL_STOP_ASSOCIATION:
652 col_set_str(pinfo->cinfo, COL_INFO, "WREPL_STOP_ASSOCIATION");
653 proto_item_append_text(winsrepl_item, ", WREPL_STOP_ASSOCIATION");
654 dissect_winsrepl_stop(tvb, pinfo,
655 offset, winsrepl_tree);
656 break;
657 case WREPL_REPLICATION:
658 dissect_winsrepl_replication(tvb, pinfo,
659 offset, winsrepl_item, winsrepl_tree);
660 break;
663 return tvb_captured_length(tvb);
666 static unsigned
667 get_winsrepl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
668 int offset, void *data _U_)
670 unsigned pdu_len;
672 pdu_len=tvb_get_ntohl(tvb, offset);
673 return pdu_len+4;
676 static int
677 dissect_winsrepl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
679 tcp_dissect_pdus(tvb, pinfo, parent_tree, winsrepl_reassemble, 4, get_winsrepl_pdu_len, dissect_winsrepl_pdu, data);
680 return tvb_captured_length(tvb);
683 void
684 proto_register_winsrepl(void)
686 static hf_register_info hf[] = {
687 { &hf_winsrepl_size, {
688 "Packet Size", "winsrepl.size",
689 FT_UINT32, BASE_DEC, NULL, 0x0,
690 "WINS Replication Packet Size", HFILL }},
692 { &hf_winsrepl_opcode, {
693 "Opcode", "winsrepl.opcode",
694 FT_UINT32, BASE_HEX, NULL, 0x0,
695 "WINS Replication Opcode", HFILL }},
697 { &hf_winsrepl_assoc_ctx, {
698 "Assoc_Ctx", "winsrepl.assoc_ctx",
699 FT_UINT32, BASE_HEX, NULL, 0x0,
700 "WINS Replication Assoc_Ctx", HFILL }},
702 { &hf_winsrepl_mess_type, {
703 "Message_Type", "winsrepl.message_type",
704 FT_UINT32, BASE_DEC, VALS(message_type_vals), 0x0,
705 "WINS Replication Message_Type", HFILL }},
707 { &hf_winsrepl_start_minor_version, {
708 "Minor Version", "winsrepl.minor_version",
709 FT_UINT16, BASE_DEC, NULL, 0x0,
710 "WINS Replication Minor Version", HFILL }},
712 { &hf_winsrepl_start_major_version, {
713 "Major Version", "winsrepl.major_version",
714 FT_UINT16, BASE_DEC, NULL, 0x0,
715 "WINS Replication Major Version", HFILL }},
717 { &hf_winsrepl_stop_reason, {
718 "Reason", "winsrepl.reason",
719 FT_UINT32, BASE_HEX, NULL, 0x0,
720 "WINS Replication Reason", HFILL }},
722 { &hf_winsrepl_replication_command, {
723 "Replication Command", "winsrepl.repl_cmd",
724 FT_UINT32, BASE_HEX, VALS(replication_cmd_vals), 0x0,
725 "WINS Replication Command", HFILL }},
727 { &hf_winsrepl_owner_address, {
728 "Owner Address", "winsrepl.owner_address",
729 FT_IPv4, BASE_NONE, NULL, 0x0,
730 "WINS Replication Owner Address", HFILL }},
732 { &hf_winsrepl_owner_max_version, {
733 "Max Version", "winsrepl.max_version",
734 FT_UINT64, BASE_DEC, NULL, 0x0,
735 "WINS Replication Max Version", HFILL }},
737 { &hf_winsrepl_owner_min_version, {
738 "Min Version", "winsrepl.min_version",
739 FT_UINT64, BASE_DEC, NULL, 0x0,
740 "WINS Replication Min Version", HFILL }},
742 { &hf_winsrepl_owner_type, {
743 "Owner Type", "winsrepl.owner_type",
744 FT_UINT32, BASE_DEC, NULL, 0x0,
745 "WINS Replication Owner Type", HFILL }},
747 { &hf_winsrepl_table_partner_count, {
748 "Partner Count", "winsrepl.partner_count",
749 FT_UINT32, BASE_DEC, NULL, 0x0,
750 "WINS Replication Partner Count", HFILL }},
752 { &hf_winsrepl_table_initiator, {
753 "Initiator", "winsrepl.initiator",
754 FT_IPv4, BASE_NONE, NULL, 0x0,
755 "WINS Replication Initiator", HFILL }},
757 { &hf_winsrepl_ip_owner, {
758 "IP Owner", "winsrepl.ip_owner",
759 FT_IPv4, BASE_NONE, NULL, 0x0,
760 "WINS Replication IP Owner", HFILL }},
762 { &hf_winsrepl_ip_ip, {
763 "IP Address", "winsrepl.ip_address",
764 FT_IPv4, BASE_NONE, NULL, 0x0,
765 "WINS Replication IP Address", HFILL }},
767 { &hf_winsrepl_addr_list_num_ips, {
768 "Num IPs", "winsrepl.num_ips",
769 FT_UINT32, BASE_DEC, NULL, 0x0,
770 "WINS Replication Num IPs", HFILL }},
772 { &hf_winsrepl_name_len, {
773 "Name Len", "winsrepl.name_len",
774 FT_UINT32, BASE_DEC, NULL, 0x0,
775 "WINS Replication Name Len", HFILL }},
777 { &hf_winsrepl_name_flags, {
778 "Name Flags", "winsrepl.name_flags",
779 FT_UINT32, BASE_HEX, NULL, 0x0,
780 "WINS Replication Name Flags", HFILL }},
782 { &hf_winsrepl_name_flags_rectype, {
783 "Record Type", "winsrepl.name_flags.rectype",
784 FT_UINT32, BASE_HEX, VALS(rectype_vals), 0x00000003,
785 "WINS Replication Name Flags Record Type", HFILL }},
787 { &hf_winsrepl_name_flags_recstate, {
788 "Record State", "winsrepl.name_flags.recstate",
789 FT_UINT32, BASE_HEX, VALS(recstate_vals), 0x0000000C,
790 "WINS Replication Name Flags Record State", HFILL }},
792 { &hf_winsrepl_name_flags_local, {
793 "Local", "winsrepl.name_flags.local",
794 FT_BOOLEAN, 32, NULL, 0x00000010,
795 "WINS Replication Name Flags Local Flag", HFILL }},
797 { &hf_winsrepl_name_flags_hosttype, {
798 "Host Type", "winsrepl.name_flags.hosttype",
799 FT_UINT32, BASE_HEX, VALS(hosttype_vals), 0x00000060,
800 "WINS Replication Name Flags Host Type", HFILL }},
802 { &hf_winsrepl_name_flags_static, {
803 "Static", "winsrepl.name_flags.static",
804 FT_BOOLEAN, 32, NULL, 0x00000080,
805 "WINS Replication Name Flags Static Flag", HFILL }},
807 { &hf_winsrepl_name_group_flag, {
808 "Name Group Flag", "winsrepl.name_group_flag",
809 FT_UINT32, BASE_HEX, NULL, 0x0,
810 "WINS Replication Name Group Flag", HFILL }},
812 { &hf_winsrepl_name_version_id, {
813 "Name Version Id", "winsrepl.name_version_id",
814 FT_UINT64, BASE_DEC, NULL, 0x0,
815 "WINS Replication Name Version Id", HFILL }},
817 { &hf_winsrepl_name_unknown, {
818 "Unknown IP", "winsrepl.unknown",
819 FT_IPv4, BASE_NONE, NULL, 0x0,
820 "WINS Replication Unknown IP", HFILL }},
822 { &hf_winsrepl_reply_num_names, {
823 "Num Names", "winsrepl.num_names",
824 FT_UINT32, BASE_DEC, NULL, 0x0,
825 "WINS Replication Num Names", HFILL }},
828 static int *ett[] = {
829 &ett_winsrepl,
830 &ett_winsrepl_start,
831 &ett_winsrepl_stop,
832 &ett_winsrepl_replication,
833 &ett_winsrepl_owner,
834 &ett_winsrepl_table_reply,
835 &ett_winsrepl_ip,
836 &ett_winsrepl_addr_list,
837 &ett_winsrepl_name,
838 &ett_winsrepl_send_reply,
839 &ett_winsrepl_flags,
842 static ei_register_info ei[] = {
843 { &ei_winsrepl_name_len, { "winsrepl.name_len.invalid", PI_MALFORMED, PI_ERROR, "Bad name length", EXPFILL }},
846 module_t *winsrepl_module;
847 expert_module_t* expert_winsrepl;
849 proto_winsrepl = proto_register_protocol("WINS (Windows Internet Name Service) Replication",
850 "WINS-Replication", "winsrepl");
851 proto_register_subtree_array(ett, array_length(ett));
852 proto_register_field_array(proto_winsrepl, hf, array_length(hf));
853 expert_winsrepl = expert_register_protocol(proto_winsrepl);
854 expert_register_field_array(expert_winsrepl, ei, array_length(ei));
855 winsrepl_handle = register_dissector("winsrepl", dissect_winsrepl, proto_winsrepl);
857 winsrepl_module = prefs_register_protocol(proto_winsrepl, NULL);
858 prefs_register_bool_preference(winsrepl_module, "reassemble",
859 "Reassemble WINS-Replication messages spanning multiple TCP segments",
860 "Whether the WINS-Replication dissector should reassemble messages spanning multiple TCP segments."
861 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
862 &winsrepl_reassemble);
865 void
866 proto_reg_handoff_winsrepl(void)
868 dissector_add_uint_with_preference("tcp.port", WINS_REPLICATION_PORT, winsrepl_handle);
872 * Editor modelines - https://www.wireshark.org/tools/modelines.html
874 * Local variables:
875 * c-basic-offset: 8
876 * tab-width: 8
877 * indent-tabs-mode: t
878 * End:
880 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
881 * :indentSize=8:tabSize=8:noTabs=false: