Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-winsrepl.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * packet-winsrepl.c
3
 *
4
 * Routines for WINS Replication packet dissection
5
 *
6
 * Copyright 2005 Stefan Metzmacher <metze@samba.org>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
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>
22
23
#include "packet-netbios.h"
24
25
#include "packet-tcp.h"
26
27
void proto_register_winsrepl(void);
28
void proto_reg_handoff_winsrepl(void);
29
static dissector_handle_t winsrepl_handle;
30
31
static bool winsrepl_reassemble = true;
32
33
static int proto_winsrepl;
34
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;
39
40
static int hf_winsrepl_start_minor_version;
41
static int hf_winsrepl_start_major_version;
42
43
static int hf_winsrepl_stop_reason;
44
45
static int hf_winsrepl_replication_command;
46
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;
51
52
static int hf_winsrepl_table_partner_count;
53
static int hf_winsrepl_table_initiator;
54
55
static int hf_winsrepl_ip_owner;
56
static int hf_winsrepl_ip_ip;
57
static int hf_winsrepl_addr_list_num_ips;
58
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;
69
70
static int hf_winsrepl_reply_num_names;
71
72
static int ett_winsrepl;
73
74
static int ett_winsrepl_start;
75
static int ett_winsrepl_stop;
76
static int ett_winsrepl_replication;
77
78
static int ett_winsrepl_owner;
79
static int ett_winsrepl_table_reply;
80
81
static int ett_winsrepl_ip;
82
static int ett_winsrepl_addr_list;
83
84
static int ett_winsrepl_name;
85
static int ett_winsrepl_send_reply;
86
87
static int ett_winsrepl_flags;
88
89
static expert_field ei_winsrepl_name_len;
90
91
14
#define WINS_REPLICATION_PORT ( 42 )
92
#define WREPL_OPCODE_BITS ( 0x7800 )
93
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
103
};
104
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
110
};
111
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}
122
};
123
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}
130
};
131
132
0
#define WREPL_NAME_TYPE_MASK    0x03
133
134
0
#define WREPL_NAME_TYPE_UNIQUE    0x00
135
0
#define WREPL_NAME_TYPE_NORMAL_GROUP  0x01
136
0
#define WREPL_NAME_TYPE_SPECIAL_GROUP 0x02
137
0
#define WREPL_NAME_TYPE_MULTIHOMED  0x03
138
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}
145
};
146
147
static const value_string recstate_vals[] = {
148
  {0x00,  "Active"},
149
  {0x01,  "Released"},
150
  {0x02,  "Tombstoned"},
151
  {0x03,  "Deleted"},
152
  {0, NULL}
153
};
154
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}
161
};
162
163
static int
164
dissect_winsrepl_start(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
165
           int winsrepl_offset, proto_tree *winsrepl_tree)
166
10
{
167
10
  proto_tree *start_tree;
168
169
10
  start_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
170
10
                  ett_winsrepl_start, NULL, "WREPL_START_ASSOCIATION");
171
172
  /* ASSOC_CTX */
173
10
  proto_tree_add_item(start_tree, hf_winsrepl_assoc_ctx, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
174
10
  winsrepl_offset += 4;
175
176
  /* MINOR VERSION */
177
10
  proto_tree_add_item(start_tree, hf_winsrepl_start_minor_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
178
10
  winsrepl_offset += 2;
179
180
  /* MAJOR VERSION */
181
10
  proto_tree_add_item(start_tree, hf_winsrepl_start_major_version, winsrepl_tvb, winsrepl_offset, 2, ENC_BIG_ENDIAN);
182
10
  winsrepl_offset += 2;
183
184
10
  return winsrepl_offset;
185
10
}
186
187
static int
188
dissect_winsrepl_stop(tvbuff_t *winsrepl_tvb, _U_ packet_info *pinfo,
189
          int winsrepl_offset, proto_tree *winsrepl_tree)
190
0
{
191
0
  uint32_t reason;
192
0
  proto_item *stop_item;
193
0
  proto_tree *stop_tree;
194
195
0
  stop_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
196
0
              ett_winsrepl_stop, &stop_item, "WREPL_STOP_ASSOCIATION");
197
198
  /* REASON */
199
0
  reason = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
200
0
  proto_tree_add_uint(stop_tree, hf_winsrepl_stop_reason, winsrepl_tvb, winsrepl_offset, 4, reason);
201
0
  winsrepl_offset += 4;
202
203
0
  proto_item_append_text(stop_item, ", Reason: 0x%08X", reason);
204
205
0
  return winsrepl_offset;
206
0
}
207
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_)
211
1
{
212
  /* Nothing to do here */
213
1
  return winsrepl_offset;
214
1
}
215
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)
220
0
{
221
0
  proto_tree *owner_tree = NULL;
222
223
0
  if (sub_tree) {
224
0
    owner_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 24,
225
0
                        ett_winsrepl_owner, NULL, "WINS Owner [%u]", idx);
226
0
  } else if (winsrepl_tree) {
227
0
    owner_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 24,
228
0
                        ett_winsrepl_owner, NULL, "WINS Owner");
229
0
  }
230
231
  /* ADDRESS */
232
0
  proto_tree_add_item(owner_tree, hf_winsrepl_owner_address, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
233
0
  winsrepl_offset += 4;
234
235
  /* MAX_VERSION */
236
0
  proto_tree_add_item(owner_tree, hf_winsrepl_owner_max_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
237
0
  winsrepl_offset += 8;
238
239
  /* MIN_VERSION */
240
0
  proto_tree_add_item(owner_tree, hf_winsrepl_owner_min_version, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
241
0
  winsrepl_offset += 8;
242
243
  /* TYPE */
244
0
  proto_tree_add_item(owner_tree, hf_winsrepl_owner_type, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
245
0
  winsrepl_offset += 4;
246
247
0
  return winsrepl_offset;
248
0
}
249
250
static int
251
dissect_winsrepl_table_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
252
           int winsrepl_offset, proto_tree *winsrepl_tree)
253
0
{
254
0
  proto_tree *table_tree;
255
0
  uint32_t partner_count;
256
0
  uint32_t i;
257
258
0
  table_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
259
0
                  ett_winsrepl_table_reply, NULL, "WREPL_REPL_TABLE_REPLY");
260
261
  /* PARTNER COUNT */
262
0
  partner_count = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
263
0
  proto_tree_add_uint(table_tree, hf_winsrepl_table_partner_count, winsrepl_tvb, winsrepl_offset, 4, partner_count);
264
0
  winsrepl_offset += 4;
265
266
0
  for (i=0; i < partner_count; i++) {
267
0
    winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
268
0
                    winsrepl_offset, table_tree,
269
0
                    table_tree, i);
270
0
  }
271
272
  /* INITIATOR */
273
0
  proto_tree_add_item(table_tree, hf_winsrepl_table_initiator, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
274
0
  winsrepl_offset += 4;
275
276
0
  return winsrepl_offset;
277
0
}
278
279
static int
280
dissect_winsrepl_send_request(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
281
           int winsrepl_offset, proto_tree *winsrepl_tree)
282
0
{
283
0
  winsrepl_offset = dissect_winsrepl_wins_owner(winsrepl_tvb, pinfo,
284
0
                  winsrepl_offset, winsrepl_tree,
285
0
                  NULL, 0);
286
287
0
  return winsrepl_offset;
288
0
}
289
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)
294
0
{
295
0
  proto_item *ip_item = NULL;
296
0
  proto_tree *ip_tree = NULL;
297
298
0
  if (sub_tree) {
299
0
    ip_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, 8,
300
0
        ett_winsrepl_ip, &ip_item, "WINS IP [%u]", idx);
301
0
  } else if (winsrepl_tree) {
302
0
    ip_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, 8,
303
0
        ett_winsrepl_ip, &ip_item, "WINS IP");
304
0
  }
305
306
  /* OWNER */
307
0
  proto_tree_add_item(ip_tree, hf_winsrepl_ip_owner, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
308
0
  winsrepl_offset += 4;
309
310
  /* IP */
311
0
  *addr = tvb_get_ipv4(winsrepl_tvb, winsrepl_offset);
312
0
  proto_tree_add_ipv4(ip_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, *addr);
313
0
  proto_item_append_text(ip_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
314
0
  winsrepl_offset += 4;
315
316
0
  return winsrepl_offset;
317
0
}
318
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)
323
0
{
324
0
  proto_item *addr_list_item;
325
0
  proto_tree *addr_list_tree;
326
0
  int old_offset = winsrepl_offset;
327
0
  uint32_t num_ips;
328
0
  uint32_t ip;
329
0
  uint32_t i;
330
0
  address addr;
331
0
  char* addr_str;
332
333
0
  addr_list_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
334
0
              ett_winsrepl_addr_list, &addr_list_item, "WINS Address List");
335
336
  /* NUM_IPS */
337
0
  num_ips = tvb_get_letohl(winsrepl_tvb, winsrepl_offset);
338
0
  proto_tree_add_uint(addr_list_tree, hf_winsrepl_addr_list_num_ips, winsrepl_tvb, winsrepl_offset, 4, num_ips);
339
0
  winsrepl_offset += 4;
340
341
0
  for (i=0; i < num_ips; i++) {
342
0
    winsrepl_offset = dissect_winsrepl_wins_ip(winsrepl_tvb, pinfo,
343
0
                 winsrepl_offset, addr_list_tree,
344
0
                 &ip, addr_list_tree, i);
345
0
    set_address(&addr, AT_IPv4, 4, &ip);
346
0
    addr_str = address_to_str(pinfo->pool, &addr);
347
0
    if (i == 0) {
348
0
      proto_item_append_text(parent_item, ": %s", addr_str);
349
0
      proto_item_append_text(addr_list_item, ": %s", addr_str);
350
0
    } else {
351
0
      proto_item_append_text(parent_item, ", %s", addr_str);
352
0
      proto_item_append_text(addr_list_item, ", %s", addr_str);
353
0
    }
354
0
  }
355
356
0
  proto_item_set_len(addr_list_item, winsrepl_offset - old_offset);
357
358
0
  return winsrepl_offset;
359
0
}
360
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)
365
0
{
366
0
  proto_item *name_item = NULL, *ti;
367
0
  proto_tree *name_tree = NULL;
368
0
  int old_offset = winsrepl_offset;
369
0
  tvbuff_t *name_tvb = NULL;
370
0
  uint32_t name_len;
371
0
  char  name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
372
0
  int   name_type;
373
0
  uint32_t flags;
374
0
  static int * const name_flags[] = {
375
0
    &hf_winsrepl_name_flags_rectype,
376
0
    &hf_winsrepl_name_flags_recstate,
377
0
    &hf_winsrepl_name_flags_local,
378
0
    &hf_winsrepl_name_flags_hosttype,
379
0
    &hf_winsrepl_name_flags_static,
380
0
    NULL
381
0
  };
382
383
0
  if (sub_tree) {
384
0
    name_tree = proto_tree_add_subtree_format(sub_tree, winsrepl_tvb, winsrepl_offset, -1,
385
0
                    ett_winsrepl_name, &name_item, "WINS Name [%u]", idx);
386
0
  } else if (winsrepl_tree) {
387
0
    name_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
388
0
                        ett_winsrepl_name, &name_item, "WINS Name");
389
0
  }
390
391
  /* NAME_LEN */
392
0
  name_len = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
393
0
  ti = proto_tree_add_uint(name_tree, hf_winsrepl_name_len, winsrepl_tvb, winsrepl_offset, 4, name_len);
394
0
  winsrepl_offset += 4;
395
0
  if (name_len == 0) {
396
0
    expert_add_info(pinfo, ti, &ei_winsrepl_name_len);
397
0
    return winsrepl_offset;
398
0
  }
399
400
  /* NAME: TODO! */
401
  /*
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.
408
   */
409
0
  name_tvb = tvb_new_subset_length(winsrepl_tvb, winsrepl_offset, name_len);
410
0
  netbios_add_name("Name", name_tvb, 0, name_tree);
411
0
  name_type = get_netbios_name(name_tvb, 0, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
412
0
  proto_item_append_text(name_item, ": %s<%02x>", name_str, name_type);
413
0
  winsrepl_offset += name_len;
414
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
419
   */
420
0
  winsrepl_offset += 4 - (winsrepl_offset & (4-1));
421
422
  /* FLAGS */
423
  /*
424
   * XXX - there appear to be more flag bits, but I didn't see
425
   * anything in the Samba code about them.
426
   */
427
0
  flags = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
428
0
  proto_tree_add_bitmask(name_tree, winsrepl_tvb, winsrepl_offset, hf_winsrepl_name_flags, ett_winsrepl_flags, name_flags, ENC_BIG_ENDIAN);
429
0
  winsrepl_offset += 4;
430
431
  /* GROUP_FLAG */
432
  /* XXX - is this just a Boolean? */
433
0
  proto_tree_add_item(name_tree, hf_winsrepl_name_group_flag, winsrepl_tvb, winsrepl_offset, 4, ENC_LITTLE_ENDIAN);
434
0
  winsrepl_offset += 4;
435
436
  /* Version ID */
437
0
  proto_tree_add_item(name_tree, hf_winsrepl_name_version_id, winsrepl_tvb, winsrepl_offset, 8, ENC_BIG_ENDIAN);
438
0
  winsrepl_offset += 8;
439
440
0
  switch (flags & WREPL_NAME_TYPE_MASK) {
441
442
0
  case WREPL_NAME_TYPE_UNIQUE:
443
0
  case WREPL_NAME_TYPE_NORMAL_GROUP:
444
    /* Single address */
445
0
    proto_tree_add_item(name_tree, hf_winsrepl_ip_ip, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
446
0
    proto_item_append_text(name_item, ": %s", tvb_ip_to_str(pinfo->pool, winsrepl_tvb, winsrepl_offset));
447
0
    winsrepl_offset += 4;
448
0
    break;
449
450
0
  case WREPL_NAME_TYPE_SPECIAL_GROUP:
451
0
  case WREPL_NAME_TYPE_MULTIHOMED:
452
    /* Address list */
453
0
    winsrepl_offset = dissect_winsrepl_wins_address_list(winsrepl_tvb, pinfo,
454
0
                     winsrepl_offset, name_tree,
455
0
                     name_item);
456
0
    break;
457
0
  }
458
459
  /* UNKNOWN, little or big endian??? */
460
0
  proto_tree_add_item(name_tree, hf_winsrepl_name_unknown, winsrepl_tvb, winsrepl_offset, 4, ENC_BIG_ENDIAN);
461
0
  winsrepl_offset += 4;
462
463
0
  proto_item_set_len(name_item, winsrepl_offset - old_offset);
464
465
0
  return winsrepl_offset;
466
0
}
467
468
static int
469
dissect_winsrepl_send_reply(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
470
          int winsrepl_offset, proto_tree *winsrepl_tree)
471
0
{
472
0
  proto_tree *rep_tree;
473
0
  uint32_t num_names;
474
0
  uint32_t i;
475
476
0
  rep_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
477
0
                ett_winsrepl_send_reply, NULL, "WREPL_REPL_SEND_REPLY");
478
479
  /* NUM NAMES */
480
0
  num_names = tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
481
0
  proto_tree_add_uint(rep_tree, hf_winsrepl_reply_num_names, winsrepl_tvb, winsrepl_offset, 4, num_names);
482
0
  winsrepl_offset += 4;
483
484
0
  for (i=0; i < num_names; i++) {
485
0
    winsrepl_offset = dissect_winsrepl_wins_name(winsrepl_tvb, pinfo,
486
0
                   winsrepl_offset, rep_tree,
487
0
                   rep_tree, i);
488
0
  }
489
490
0
  return winsrepl_offset;
491
0
}
492
493
static int
494
dissect_winsrepl_update(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
495
      int winsrepl_offset, proto_tree *winsrepl_tree)
496
0
{
497
0
  winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
498
0
                   winsrepl_offset, winsrepl_tree);
499
0
  return winsrepl_offset;
500
0
}
501
502
static int
503
dissect_winsrepl_update2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
504
       int winsrepl_offset, proto_tree *winsrepl_tree)
505
0
{
506
0
  winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
507
0
                   winsrepl_offset, winsrepl_tree);
508
0
  return winsrepl_offset;
509
0
}
510
511
static int
512
dissect_winsrepl_inform(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
513
      int winsrepl_offset, proto_tree *winsrepl_tree)
514
0
{
515
0
  winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
516
0
                   winsrepl_offset, winsrepl_tree);
517
0
  return winsrepl_offset;
518
0
}
519
520
static int
521
dissect_winsrepl_inform2(tvbuff_t *winsrepl_tvb, packet_info *pinfo,
522
       int winsrepl_offset, proto_tree *winsrepl_tree)
523
0
{
524
0
  winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
525
0
                   winsrepl_offset, winsrepl_tree);
526
0
  return winsrepl_offset;
527
0
}
528
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)
532
1
{
533
1
  proto_item *repl_item;
534
1
  proto_tree *repl_tree;
535
1
  enum wrepl_replication_cmd command;
536
537
1
  repl_tree = proto_tree_add_subtree(winsrepl_tree, winsrepl_tvb, winsrepl_offset, -1,
538
1
              ett_winsrepl_replication, &repl_item, "WREPL_REPLICATION");
539
540
  /* REPLICATION_CMD */
541
1
  command = (enum wrepl_replication_cmd)tvb_get_ntohl(winsrepl_tvb, winsrepl_offset);
542
1
  proto_tree_add_uint(repl_tree, hf_winsrepl_replication_command, winsrepl_tvb, winsrepl_offset, 4, command);
543
1
  winsrepl_offset += 4;
544
545
1
  switch (command) {
546
1
    case WREPL_REPL_TABLE_QUERY:
547
1
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_QUERY");
548
1
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_QUERY");
549
1
      proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_QUERY");
550
1
      winsrepl_offset = dissect_winsrepl_table_query(winsrepl_tvb, pinfo,
551
1
                       winsrepl_offset, repl_tree);
552
1
      break;
553
0
    case WREPL_REPL_TABLE_REPLY:
554
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_TABLE_REPLY");
555
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_TABLE_REPLY");
556
0
      proto_item_append_text(repl_item, ", WREPL_REPL_TABLE_REPLY");
557
0
      winsrepl_offset = dissect_winsrepl_table_reply(winsrepl_tvb, pinfo,
558
0
                       winsrepl_offset, repl_tree);
559
0
      break;
560
0
    case WREPL_REPL_SEND_REQUEST:
561
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REQUEST");
562
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REQUEST");
563
0
      proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REQUEST");
564
0
      winsrepl_offset = dissect_winsrepl_send_request(winsrepl_tvb, pinfo,
565
0
                  winsrepl_offset, repl_tree);
566
0
      break;
567
0
    case WREPL_REPL_SEND_REPLY:
568
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_SEND_REPLY");
569
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_SEND_REPLY");
570
0
      proto_item_append_text(repl_item, ", WREPL_REPL_SEND_REPLY");
571
0
      winsrepl_offset = dissect_winsrepl_send_reply(winsrepl_tvb, pinfo,
572
0
                      winsrepl_offset, repl_tree);
573
0
      break;
574
0
    case WREPL_REPL_UPDATE:
575
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE");
576
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_UPDATE");
577
0
      proto_item_append_text(repl_item, ", WREPL_REPL_UPDATE");
578
0
      winsrepl_offset = dissect_winsrepl_update(winsrepl_tvb, pinfo,
579
0
                  winsrepl_offset, repl_tree);
580
0
      break;
581
0
    case WREPL_REPL_UPDATE2:
582
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_UPDATE2");
583
0
      proto_item_append_text(winsrepl_item, ",WREPL_REPL_UPDATE2");
584
0
      proto_item_append_text(repl_item, ",WREPL_REPL_UPDATE2");
585
0
      winsrepl_offset = dissect_winsrepl_update2(winsrepl_tvb, pinfo,
586
0
                   winsrepl_offset, repl_tree);
587
0
      break;
588
0
    case WREPL_REPL_INFORM:
589
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM");
590
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM");
591
0
      proto_item_append_text(repl_item, ", WREPL_REPL_INFORM");
592
0
      winsrepl_offset = dissect_winsrepl_inform(winsrepl_tvb, pinfo,
593
0
                  winsrepl_offset, repl_tree);
594
0
      break;
595
0
    case WREPL_REPL_INFORM2:
596
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_REPL_INFORM2");
597
0
      proto_item_append_text(winsrepl_item, ", WREPL_REPL_INFORM2");
598
0
      proto_item_append_text(repl_item, ", WREPL_REPL_INFORM2");
599
0
      winsrepl_offset = dissect_winsrepl_inform2(winsrepl_tvb, pinfo,
600
0
                   winsrepl_offset, repl_tree);
601
0
      break;
602
1
  }
603
604
1
  return winsrepl_offset;
605
1
}
606
607
static int
608
dissect_winsrepl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
609
271
{
610
271
  int offset = 0;
611
271
  proto_item *winsrepl_item;
612
271
  proto_tree *winsrepl_tree;
613
271
  enum wrepl_mess_type mess_type;
614
615
271
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "WINS-Replication");
616
271
  col_clear(pinfo->cinfo, COL_INFO);
617
618
271
  winsrepl_item = proto_tree_add_item(parent_tree, proto_winsrepl, tvb, offset, -1, ENC_NA);
619
271
  winsrepl_tree = proto_item_add_subtree(winsrepl_item, ett_winsrepl);
620
621
  /* SIZE */
622
271
  proto_tree_add_item(winsrepl_tree, hf_winsrepl_size, tvb, offset, 4, ENC_BIG_ENDIAN);
623
271
  offset += 4;
624
625
  /* OPCODE */
626
271
  proto_tree_add_item(winsrepl_tree, hf_winsrepl_opcode, tvb, offset, 4, ENC_BIG_ENDIAN);
627
271
  offset += 4;
628
629
  /* ASSOC_CTX */
630
271
  proto_tree_add_item(winsrepl_tree, hf_winsrepl_assoc_ctx, tvb, offset, 4, ENC_BIG_ENDIAN);
631
271
  offset += 4;
632
633
  /* MESSAGE_TYPE */
634
271
  mess_type = (enum wrepl_mess_type)tvb_get_ntohl(tvb, offset);
635
271
  proto_tree_add_uint(winsrepl_tree, hf_winsrepl_mess_type, tvb, offset, 4, mess_type);
636
271
  offset += 4;
637
638
271
  switch (mess_type) {
639
9
    case WREPL_START_ASSOCIATION:
640
9
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION");
641
9
      proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION");
642
9
      dissect_winsrepl_start(tvb, pinfo,
643
9
              offset, winsrepl_tree);
644
9
      break;
645
1
    case WREPL_START_ASSOCIATION_REPLY:
646
1
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_START_ASSOCIATION_REPLY");
647
1
      proto_item_append_text(winsrepl_item, ", WREPL_START_ASSOCIATION_REPLY");
648
1
      dissect_winsrepl_start(tvb, pinfo,
649
1
              offset, winsrepl_tree);
650
1
      break;
651
0
    case WREPL_STOP_ASSOCIATION:
652
0
      col_set_str(pinfo->cinfo, COL_INFO, "WREPL_STOP_ASSOCIATION");
653
0
      proto_item_append_text(winsrepl_item, ", WREPL_STOP_ASSOCIATION");
654
0
      dissect_winsrepl_stop(tvb, pinfo,
655
0
                   offset, winsrepl_tree);
656
0
      break;
657
1
    case WREPL_REPLICATION:
658
1
      dissect_winsrepl_replication(tvb, pinfo,
659
1
                    offset, winsrepl_item, winsrepl_tree);
660
1
      break;
661
271
  }
662
663
36
  return tvb_captured_length(tvb);
664
271
}
665
666
static unsigned
667
get_winsrepl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
668
                     int offset, void *data _U_)
669
276
{
670
276
  unsigned pdu_len;
671
672
276
  pdu_len=tvb_get_ntohl(tvb, offset);
673
276
  return pdu_len+4;
674
276
}
675
676
static int
677
dissect_winsrepl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
678
27
{
679
27
  tcp_dissect_pdus(tvb, pinfo, parent_tree, winsrepl_reassemble, 4, get_winsrepl_pdu_len, dissect_winsrepl_pdu, data);
680
27
  return tvb_captured_length(tvb);
681
27
}
682
683
void
684
proto_register_winsrepl(void)
685
14
{
686
14
  static hf_register_info hf[] = {
687
14
    { &hf_winsrepl_size, {
688
14
      "Packet Size", "winsrepl.size",
689
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
690
14
      "WINS Replication Packet Size", HFILL }},
691
692
14
    { &hf_winsrepl_opcode, {
693
14
      "Opcode", "winsrepl.opcode",
694
14
      FT_UINT32, BASE_HEX, NULL, 0x0,
695
14
      "WINS Replication Opcode", HFILL }},
696
697
14
    { &hf_winsrepl_assoc_ctx, {
698
14
      "Assoc_Ctx", "winsrepl.assoc_ctx",
699
14
      FT_UINT32, BASE_HEX, NULL, 0x0,
700
14
      "WINS Replication Assoc_Ctx", HFILL }},
701
702
14
    { &hf_winsrepl_mess_type, {
703
14
      "Message_Type", "winsrepl.message_type",
704
14
      FT_UINT32, BASE_DEC, VALS(message_type_vals), 0x0,
705
14
      "WINS Replication Message_Type", HFILL }},
706
707
14
    { &hf_winsrepl_start_minor_version, {
708
14
      "Minor Version", "winsrepl.minor_version",
709
14
      FT_UINT16, BASE_DEC, NULL, 0x0,
710
14
      "WINS Replication Minor Version", HFILL }},
711
712
14
    { &hf_winsrepl_start_major_version, {
713
14
      "Major Version", "winsrepl.major_version",
714
14
      FT_UINT16, BASE_DEC, NULL, 0x0,
715
14
      "WINS Replication Major Version", HFILL }},
716
717
14
    { &hf_winsrepl_stop_reason, {
718
14
      "Reason", "winsrepl.reason",
719
14
      FT_UINT32, BASE_HEX, NULL, 0x0,
720
14
      "WINS Replication Reason", HFILL }},
721
722
14
    { &hf_winsrepl_replication_command, {
723
14
      "Replication Command", "winsrepl.repl_cmd",
724
14
      FT_UINT32, BASE_HEX, VALS(replication_cmd_vals), 0x0,
725
14
      "WINS Replication Command", HFILL }},
726
727
14
    { &hf_winsrepl_owner_address, {
728
14
      "Owner Address", "winsrepl.owner_address",
729
14
      FT_IPv4, BASE_NONE, NULL, 0x0,
730
14
      "WINS Replication Owner Address", HFILL }},
731
732
14
    { &hf_winsrepl_owner_max_version, {
733
14
      "Max Version", "winsrepl.max_version",
734
14
      FT_UINT64, BASE_DEC, NULL, 0x0,
735
14
      "WINS Replication Max Version", HFILL }},
736
737
14
    { &hf_winsrepl_owner_min_version, {
738
14
      "Min Version", "winsrepl.min_version",
739
14
      FT_UINT64, BASE_DEC, NULL, 0x0,
740
14
      "WINS Replication Min Version", HFILL }},
741
742
14
    { &hf_winsrepl_owner_type, {
743
14
      "Owner Type", "winsrepl.owner_type",
744
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
745
14
      "WINS Replication Owner Type", HFILL }},
746
747
14
    { &hf_winsrepl_table_partner_count, {
748
14
      "Partner Count", "winsrepl.partner_count",
749
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
750
14
      "WINS Replication Partner Count", HFILL }},
751
752
14
    { &hf_winsrepl_table_initiator, {
753
14
      "Initiator", "winsrepl.initiator",
754
14
      FT_IPv4, BASE_NONE, NULL, 0x0,
755
14
      "WINS Replication Initiator", HFILL }},
756
757
14
    { &hf_winsrepl_ip_owner, {
758
14
      "IP Owner", "winsrepl.ip_owner",
759
14
      FT_IPv4, BASE_NONE, NULL, 0x0,
760
14
      "WINS Replication IP Owner", HFILL }},
761
762
14
    { &hf_winsrepl_ip_ip, {
763
14
      "IP Address", "winsrepl.ip_address",
764
14
      FT_IPv4, BASE_NONE, NULL, 0x0,
765
14
      "WINS Replication IP Address", HFILL }},
766
767
14
    { &hf_winsrepl_addr_list_num_ips, {
768
14
      "Num IPs", "winsrepl.num_ips",
769
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
770
14
      "WINS Replication Num IPs", HFILL }},
771
772
14
    { &hf_winsrepl_name_len, {
773
14
      "Name Len", "winsrepl.name_len",
774
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
775
14
      "WINS Replication Name Len", HFILL }},
776
777
14
    { &hf_winsrepl_name_flags, {
778
14
      "Name Flags", "winsrepl.name_flags",
779
14
      FT_UINT32, BASE_HEX, NULL, 0x0,
780
14
      "WINS Replication Name Flags", HFILL }},
781
782
14
    { &hf_winsrepl_name_flags_rectype, {
783
14
      "Record Type", "winsrepl.name_flags.rectype",
784
14
      FT_UINT32, BASE_HEX, VALS(rectype_vals), 0x00000003,
785
14
      "WINS Replication Name Flags Record Type", HFILL }},
786
787
14
    { &hf_winsrepl_name_flags_recstate, {
788
14
      "Record State", "winsrepl.name_flags.recstate",
789
14
      FT_UINT32, BASE_HEX, VALS(recstate_vals), 0x0000000C,
790
14
      "WINS Replication Name Flags Record State", HFILL }},
791
792
14
    { &hf_winsrepl_name_flags_local, {
793
14
      "Local", "winsrepl.name_flags.local",
794
14
      FT_BOOLEAN, 32, NULL, 0x00000010,
795
14
      "WINS Replication Name Flags Local Flag", HFILL }},
796
797
14
    { &hf_winsrepl_name_flags_hosttype, {
798
14
      "Host Type", "winsrepl.name_flags.hosttype",
799
14
      FT_UINT32, BASE_HEX, VALS(hosttype_vals), 0x00000060,
800
14
      "WINS Replication Name Flags Host Type", HFILL }},
801
802
14
    { &hf_winsrepl_name_flags_static, {
803
14
      "Static", "winsrepl.name_flags.static",
804
14
      FT_BOOLEAN, 32, NULL, 0x00000080,
805
14
      "WINS Replication Name Flags Static Flag", HFILL }},
806
807
14
    { &hf_winsrepl_name_group_flag, {
808
14
      "Name Group Flag", "winsrepl.name_group_flag",
809
14
      FT_UINT32, BASE_HEX, NULL, 0x0,
810
14
      "WINS Replication Name Group Flag", HFILL }},
811
812
14
    { &hf_winsrepl_name_version_id, {
813
14
      "Name Version Id", "winsrepl.name_version_id",
814
14
      FT_UINT64, BASE_DEC, NULL, 0x0,
815
14
      "WINS Replication Name Version Id", HFILL }},
816
817
14
    { &hf_winsrepl_name_unknown, {
818
14
      "Unknown IP", "winsrepl.unknown",
819
14
      FT_IPv4, BASE_NONE, NULL, 0x0,
820
14
      "WINS Replication Unknown IP", HFILL }},
821
822
14
    { &hf_winsrepl_reply_num_names, {
823
14
      "Num Names", "winsrepl.num_names",
824
14
      FT_UINT32, BASE_DEC, NULL, 0x0,
825
14
      "WINS Replication Num Names", HFILL }},
826
14
  };
827
828
14
  static int *ett[] = {
829
14
    &ett_winsrepl,
830
14
    &ett_winsrepl_start,
831
14
    &ett_winsrepl_stop,
832
14
    &ett_winsrepl_replication,
833
14
    &ett_winsrepl_owner,
834
14
    &ett_winsrepl_table_reply,
835
14
    &ett_winsrepl_ip,
836
14
    &ett_winsrepl_addr_list,
837
14
    &ett_winsrepl_name,
838
14
    &ett_winsrepl_send_reply,
839
14
    &ett_winsrepl_flags,
840
14
  };
841
842
14
  static ei_register_info ei[] = {
843
14
    { &ei_winsrepl_name_len, { "winsrepl.name_len.invalid", PI_MALFORMED, PI_ERROR, "Bad name length", EXPFILL }},
844
14
  };
845
846
14
  module_t *winsrepl_module;
847
14
  expert_module_t* expert_winsrepl;
848
849
14
  proto_winsrepl = proto_register_protocol("WINS (Windows Internet Name Service) Replication",
850
14
             "WINS-Replication", "winsrepl");
851
14
  proto_register_subtree_array(ett, array_length(ett));
852
14
  proto_register_field_array(proto_winsrepl, hf, array_length(hf));
853
14
  expert_winsrepl = expert_register_protocol(proto_winsrepl);
854
14
  expert_register_field_array(expert_winsrepl, ei, array_length(ei));
855
14
  winsrepl_handle = register_dissector("winsrepl", dissect_winsrepl, proto_winsrepl);
856
857
14
  winsrepl_module = prefs_register_protocol(proto_winsrepl, NULL);
858
14
  prefs_register_bool_preference(winsrepl_module, "reassemble",
859
14
    "Reassemble WINS-Replication messages spanning multiple TCP segments",
860
14
    "Whether the WINS-Replication dissector should reassemble messages spanning multiple TCP segments."
861
14
    " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
862
14
    &winsrepl_reassemble);
863
14
}
864
865
void
866
proto_reg_handoff_winsrepl(void)
867
14
{
868
14
  dissector_add_uint_with_preference("tcp.port", WINS_REPLICATION_PORT, winsrepl_handle);
869
14
}
870
871
/*
872
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
873
 *
874
 * Local variables:
875
 * c-basic-offset: 8
876
 * tab-width: 8
877
 * indent-tabs-mode: t
878
 * End:
879
 *
880
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
881
 * :indentSize=8:tabSize=8:noTabs=false:
882
 */