Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ipvs-syncd.c
Line
Count
Source
1
/* packet-ipvs-syncd.c   2001 Ronnie Sahlberg <See AUTHORS for email>
2
 * Routines for IGMP packet disassembly
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
13
#include <epan/packet.h>
14
15
void proto_register_ipvs_syncd(void);
16
void proto_reg_handoff_ipvs_syncd(void);
17
18
static dissector_handle_t ipvs_syncd_handle;
19
20
static int proto_ipvs_syncd;
21
static int hf_conn_count;
22
static int hf_syncid;
23
static int hf_size;
24
static int hf_resv;
25
static int hf_version;
26
static int hf_proto;
27
static int hf_cport;
28
static int hf_vport;
29
static int hf_dport;
30
static int hf_caddr;
31
static int hf_vaddr;
32
static int hf_daddr;
33
static int hf_flags;
34
static int hf_flags_conn_type;
35
static int hf_flags_hashed_entry;
36
static int hf_flags_no_output_packets;
37
static int hf_flags_conn_not_established;
38
static int hf_flags_adjust_output_seq;
39
static int hf_flags_adjust_input_seq;
40
static int hf_flags_no_client_port_set;
41
static int hf_state;
42
static int hf_in_seq_init;
43
static int hf_in_seq_delta;
44
static int hf_in_seq_pdelta;
45
static int hf_out_seq_init;
46
static int hf_out_seq_delta;
47
static int hf_out_seq_pdelta;
48
49
/* Payload v1 */
50
static int hf_type;
51
static int hf_ver;
52
static int hf_size_v1;
53
static int hf_flags_v1;
54
static int hf_fwmark;
55
static int hf_timeout;
56
static int hf_caddr6;
57
static int hf_vaddr6;
58
static int hf_daddr6;
59
60
static int ett_ipvs_syncd;
61
static int ett_conn;
62
static int ett_flags;
63
64
#define IPVS_SYNCD_MC_GROUP "224.0.0.18"
65
16
#define IPVS_SYNCD_PORT 8848 /* Not IANA registered */
66
67
static const value_string proto_strings[] = {
68
  {0x06, "TCP"},
69
  {0x11, "UDP"},
70
  {0x00, NULL},
71
};
72
73
static const value_string state_strings[] = {
74
  {0x00, "Input"},
75
  {0x04, "Output"},
76
  {0x08, "Input Only"},
77
  {0x00, NULL},
78
};
79
80
static const value_string type_strings[] = {
81
  {0x0, "IPv4"},
82
  {0x2, "IPv6"},
83
  {0x00, NULL},
84
};
85
86
/*
87
 *  IPVS Connection Flags
88
 *  Pulled from include/net/ip_vs.h in linux kernel source
89
 */
90
#define IP_VS_CONN_F_FWD_MASK         0x0007    /* mask for the fwd methods */
91
#define IP_VS_CONN_F_MASQ             0x0000    /* masquerading */
92
#define IP_VS_CONN_F_LOCALNODE        0x0001    /* local node */
93
#define IP_VS_CONN_F_TUNNEL           0x0002    /* tunneling */
94
#define IP_VS_CONN_F_DROUTE           0x0003    /* direct routing */
95
#define IP_VS_CONN_F_BYPASS           0x0004    /* cache bypass */
96
16
#define IP_VS_CONN_F_HASHED           0x0040    /* hashed entry */
97
16
#define IP_VS_CONN_F_NOOUTPUT         0x0080    /* no output packets */
98
16
#define IP_VS_CONN_F_INACTIVE         0x0100    /* not established */
99
16
#define IP_VS_CONN_F_OUT_SEQ          0x0200    /* must do output seq adjust */
100
16
#define IP_VS_CONN_F_IN_SEQ           0x0400    /* must do input seq adjust */
101
71
#define IP_VS_CONN_F_SEQ_MASK         0x0600    /* in/out sequence mask */
102
16
#define IP_VS_CONN_F_NO_CPORT         0x0800    /* no client port set yet */
103
104
static const value_string connection_type_strings[] = {
105
  {IP_VS_CONN_F_MASQ,  "Masquerade"},
106
  {IP_VS_CONN_F_LOCALNODE, "Local Node"},
107
  {IP_VS_CONN_F_TUNNEL,  "Tunnel"},
108
  {IP_VS_CONN_F_DROUTE,  "Direct Routing"},
109
  {0x00, NULL},
110
};
111
112
113
static int
114
dissect_ipvs_syncd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
115
27
{
116
27
  proto_tree *tree;
117
27
  proto_item *item;
118
27
  int         offset = 0;
119
27
  uint8_t     cnt    = 0;
120
27
  uint8_t     version = 0;
121
27
  int         conn   = 0;
122
123
27
  item = proto_tree_add_item(parent_tree, proto_ipvs_syncd, tvb, offset, -1, ENC_NA);
124
27
  tree = proto_item_add_subtree(item, ett_ipvs_syncd);
125
126
127
27
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPVS");
128
27
  col_clear(pinfo->cinfo, COL_INFO);
129
130
27
  cnt = tvb_get_uint8(tvb, offset);
131
27
  if(cnt == 0) { //Version 1 (or after...) first byte is reserved
132
13
    proto_tree_add_item(tree, hf_resv, tvb, offset, 1, ENC_NA);
133
13
    col_set_str(pinfo->cinfo, COL_INFO, "v1");
134
14
  } else {
135
14
    proto_tree_add_item(tree, hf_conn_count, tvb, offset, 1, ENC_BIG_ENDIAN);
136
14
    col_set_str(pinfo->cinfo, COL_INFO, "v0");
137
14
  }
138
27
  offset += 1;
139
140
27
  proto_tree_add_item(tree, hf_syncid, tvb, offset, 1, ENC_BIG_ENDIAN);
141
27
  offset += 1;
142
143
27
  proto_tree_add_item(tree, hf_size, tvb, offset, 2, ENC_BIG_ENDIAN);
144
27
  offset += 2;
145
146
27
  if(cnt == 0) { //Version 1 (or after...)
147
13
    proto_tree_add_item_ret_uint8(tree, hf_conn_count, tvb, offset, 1, ENC_BIG_ENDIAN, &cnt);
148
13
    offset += 1;
149
150
13
    proto_tree_add_item_ret_uint8(tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN, &version);
151
13
    offset += 1;
152
153
13
    proto_tree_add_item(tree, hf_resv, tvb, offset, 2, ENC_NA);
154
13
    offset += 2;
155
13
  }
156
27
  col_append_fstr(pinfo->cinfo, COL_INFO, " %u Connection(s)", cnt);
157
158
174
  for (conn = 0; conn < cnt; conn++)
159
147
  {
160
147
    if(version) {
161
162
76
      proto_tree *ctree;
163
76
      uint8_t type;
164
76
      uint16_t size;
165
166
76
      ctree = proto_tree_add_subtree_format(tree, tvb, offset, 36, ett_conn, NULL,
167
76
                    "Connection #%d", conn+1);
168
169
76
      proto_tree_add_item_ret_uint8(ctree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN, &type);
170
76
      offset += 1;
171
172
76
      proto_tree_add_item(ctree, hf_proto, tvb, offset, 1, ENC_BIG_ENDIAN);
173
76
      offset += 1;
174
175
76
      size = (tvb_get_ntohs(tvb, offset) & 0x1FFF);
176
76
      proto_item_set_len(ctree, size);
177
76
      proto_tree_add_item(ctree, hf_ver, tvb, offset, 2, ENC_BIG_ENDIAN);
178
76
      proto_tree_add_item(ctree, hf_size_v1, tvb, offset, 2, ENC_BIG_ENDIAN);
179
76
      offset += 2;
180
181
76
      proto_tree_add_item(ctree, hf_flags_v1, tvb, offset, 4, ENC_BIG_ENDIAN);
182
76
      offset += 4;
183
184
76
      proto_tree_add_item(ctree, hf_state, tvb, offset, 2, ENC_BIG_ENDIAN);
185
76
      offset += 2;
186
187
76
      proto_tree_add_item(ctree, hf_cport, tvb, offset, 2, ENC_BIG_ENDIAN);
188
76
      offset += 2;
189
190
76
      proto_tree_add_item(ctree, hf_vport, tvb, offset, 2, ENC_BIG_ENDIAN);
191
76
      offset += 2;
192
193
76
      proto_tree_add_item(ctree, hf_dport, tvb, offset, 2, ENC_BIG_ENDIAN);
194
76
      offset += 2;
195
196
76
      proto_tree_add_item(ctree, hf_fwmark, tvb, offset, 4, ENC_BIG_ENDIAN);
197
76
      offset += 4;
198
199
76
      proto_tree_add_item(ctree, hf_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
200
76
      offset += 4;
201
202
76
      if(type == 0){ /* IPv4 */
203
204
39
        proto_tree_add_item(ctree, hf_caddr, tvb, offset, 4, ENC_BIG_ENDIAN);
205
39
        offset += 4;
206
207
39
        proto_tree_add_item(ctree, hf_vaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
208
39
        offset += 4;
209
210
39
        proto_tree_add_item(ctree, hf_daddr, tvb, offset, 4, ENC_BIG_ENDIAN);
211
39
        offset += 4;
212
39
      } else { /* IPv6 */
213
214
37
        proto_tree_add_item(ctree, hf_caddr6, tvb, offset, 16, ENC_NA);
215
37
        offset += 16;
216
217
37
        proto_tree_add_item(ctree, hf_vaddr6, tvb, offset, 16, ENC_NA);
218
37
        offset += 16;
219
220
37
        proto_tree_add_item(ctree, hf_daddr6, tvb, offset, 16, ENC_NA);
221
37
        offset += 16;
222
37
      }
223
224
76
    } else {
225
226
71
      proto_tree *ctree;
227
71
      proto_tree *ftree, *fi;
228
71
      uint16_t flags;
229
230
71
      ctree = proto_tree_add_subtree_format(tree, tvb, offset, 24, ett_conn, NULL,
231
71
                    "Connection #%d", conn+1);
232
233
71
      proto_tree_add_item(ctree, hf_resv, tvb, offset, 1, ENC_NA);
234
71
      offset += 1;
235
236
71
      proto_tree_add_item(ctree, hf_proto, tvb, offset, 1, ENC_BIG_ENDIAN);
237
71
      offset += 1;
238
239
71
      proto_tree_add_item(ctree, hf_cport, tvb, offset, 2, ENC_BIG_ENDIAN);
240
71
      offset += 2;
241
242
71
      proto_tree_add_item(ctree, hf_vport, tvb, offset, 2, ENC_BIG_ENDIAN);
243
71
      offset += 2;
244
245
71
      proto_tree_add_item(ctree, hf_dport, tvb, offset, 2, ENC_BIG_ENDIAN);
246
71
      offset += 2;
247
248
71
      proto_tree_add_item(ctree, hf_caddr, tvb, offset, 4, ENC_BIG_ENDIAN);
249
71
      offset += 4;
250
251
71
      proto_tree_add_item(ctree, hf_vaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
252
71
      offset += 4;
253
254
71
      proto_tree_add_item(ctree, hf_daddr, tvb, offset, 4, ENC_BIG_ENDIAN);
255
71
      offset += 4;
256
257
71
      fi = proto_tree_add_item_ret_uint16(ctree, hf_flags, tvb, offset, 2, ENC_BIG_ENDIAN, &flags);
258
71
      ftree = proto_item_add_subtree(fi, ett_flags);
259
71
      proto_tree_add_item(ftree, hf_flags_conn_type, tvb, offset, 2, ENC_BIG_ENDIAN);
260
71
      proto_tree_add_item(ftree, hf_flags_hashed_entry, tvb, offset, 2, ENC_BIG_ENDIAN);
261
71
      proto_tree_add_item(ftree, hf_flags_no_output_packets, tvb, offset, 2, ENC_BIG_ENDIAN);
262
71
      proto_tree_add_item(ftree, hf_flags_conn_not_established, tvb, offset, 2, ENC_BIG_ENDIAN);
263
71
      proto_tree_add_item(ftree, hf_flags_adjust_output_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
264
71
      proto_tree_add_item(ftree, hf_flags_adjust_input_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
265
71
      proto_tree_add_item(ftree, hf_flags_no_client_port_set, tvb, offset, 2, ENC_BIG_ENDIAN);
266
267
71
      offset += 2;
268
269
71
      proto_tree_add_item(ctree, hf_state, tvb, offset, 2, ENC_BIG_ENDIAN);
270
71
      offset += 2;
271
272
      /* we have full connection info */
273
71
      if ( flags & IP_VS_CONN_F_SEQ_MASK )
274
20
      {
275
20
        proto_tree_add_item(ctree, hf_in_seq_init, tvb, offset, 4, ENC_BIG_ENDIAN);
276
20
        offset += 4;
277
278
20
        proto_tree_add_item(ctree, hf_in_seq_delta, tvb, offset, 4, ENC_BIG_ENDIAN);
279
20
        offset += 4;
280
281
20
        proto_tree_add_item(ctree, hf_in_seq_pdelta, tvb, offset, 4, ENC_BIG_ENDIAN);
282
20
        offset += 4;
283
284
20
        proto_tree_add_item(ctree, hf_out_seq_init, tvb, offset, 4, ENC_BIG_ENDIAN);
285
20
        offset += 4;
286
287
20
        proto_tree_add_item(ctree, hf_out_seq_delta, tvb, offset, 4, ENC_BIG_ENDIAN);
288
20
        offset += 4;
289
290
20
        proto_tree_add_item(ctree, hf_out_seq_pdelta, tvb, offset, 4, ENC_BIG_ENDIAN);
291
20
        offset += 4;
292
293
20
      }
294
71
    }
295
296
147
  }
297
298
27
  return tvb_captured_length(tvb);
299
27
}
300
301
void
302
proto_register_ipvs_syncd(void)
303
16
{
304
16
  static hf_register_info hf[] = {
305
16
    { &hf_conn_count,
306
16
      { "Connection Count", "ipvs.conncount", FT_UINT8, BASE_DEC,
307
16
        NULL, 0, NULL, HFILL }},
308
309
16
    { &hf_syncid,
310
16
      { "Synchronization ID", "ipvs.syncid", FT_UINT8, BASE_DEC,
311
16
        NULL, 0, NULL, HFILL }},
312
313
16
    { &hf_size,
314
16
      { "Size", "ipvs.size", FT_UINT16, BASE_DEC,
315
16
        NULL, 0, NULL, HFILL }},
316
317
16
    { &hf_resv,
318
16
      { "Reserved", "ipvs.resv", FT_BYTES, BASE_NONE,
319
16
        NULL, 0, NULL, HFILL }},
320
321
16
    { &hf_version,
322
16
      { "Version", "ipvs.version", FT_UINT8, BASE_DEC,
323
16
        NULL, 0, NULL, HFILL }},
324
325
16
    { &hf_proto,
326
16
      { "Protocol", "ipvs.proto", FT_UINT8, BASE_HEX,
327
16
        VALS(proto_strings), 0, NULL, HFILL }},
328
329
16
    { &hf_cport,
330
16
      { "Client Port", "ipvs.cport", FT_UINT16, BASE_DEC,
331
16
        NULL, 0, NULL, HFILL }},
332
333
16
    { &hf_vport,
334
16
      { "Virtual Port", "ipvs.vport", FT_UINT16, BASE_DEC,
335
16
        NULL, 0, NULL, HFILL }},
336
337
16
    { &hf_dport,
338
16
      { "Destination Port", "ipvs.dport", FT_UINT16, BASE_DEC,
339
16
        NULL, 0, NULL, HFILL }},
340
341
16
    { &hf_caddr,
342
16
      { "Client Address", "ipvs.caddr", FT_IPv4, BASE_NONE,
343
16
        NULL, 0, NULL, HFILL }},
344
345
16
    { &hf_vaddr,
346
16
      { "Virtual Address", "ipvs.vaddr", FT_IPv4, BASE_NONE,
347
16
        NULL, 0, NULL, HFILL }},
348
349
16
    { &hf_daddr,
350
16
      { "Destination Address", "ipvs.daddr", FT_IPv4, BASE_NONE,
351
16
        NULL, 0, NULL, HFILL }},
352
353
16
    { &hf_flags,
354
16
      { "Flags", "ipvs.flags", FT_UINT16, BASE_HEX,
355
16
        NULL, 0, NULL, HFILL }},
356
357
16
    { &hf_flags_conn_type,
358
16
      { "Connection Type", "ipvs.flags.conn_type", FT_UINT16, BASE_HEX,
359
16
        VALS(connection_type_strings), 0x0F, NULL, HFILL }},
360
361
16
    { &hf_flags_hashed_entry,
362
16
      { "Hashed Entry", "ipvs.flags.hashed_entry", FT_BOOLEAN, 16,
363
16
        NULL, IP_VS_CONN_F_HASHED, NULL, HFILL }},
364
365
16
    { &hf_flags_no_output_packets,
366
16
      { "No Output Packets", "ipvs.flags.no_output_packets", FT_BOOLEAN, 16,
367
16
        NULL, IP_VS_CONN_F_NOOUTPUT, NULL, HFILL }},
368
369
16
    { &hf_flags_conn_not_established,
370
16
      { "Connection Not Established", "ipvs.flags.conn_not_established", FT_BOOLEAN, 16,
371
16
        NULL, IP_VS_CONN_F_INACTIVE, NULL, HFILL }},
372
373
16
    { &hf_flags_adjust_output_seq,
374
16
      { "Adjust Output Sequence", "ipvs.flags.adjust_output_seq", FT_BOOLEAN, 16,
375
16
        NULL, IP_VS_CONN_F_OUT_SEQ, NULL, HFILL }},
376
377
16
    { &hf_flags_adjust_input_seq,
378
16
      { "Adjust Input Sequence", "ipvs.flags.adjust_input_seq", FT_BOOLEAN, 16,
379
16
        NULL, IP_VS_CONN_F_IN_SEQ, NULL, HFILL }},
380
381
16
    { &hf_flags_no_client_port_set,
382
16
      { "No Client Port Set", "ipvs.flags.no_client_port_set", FT_BOOLEAN, 16,
383
16
        NULL, IP_VS_CONN_F_NO_CPORT, NULL, HFILL }},
384
385
16
    { &hf_state,
386
16
      { "State", "ipvs.state", FT_UINT16, BASE_HEX,
387
16
        VALS(state_strings), 0, NULL, HFILL }},
388
389
16
    { &hf_in_seq_init,
390
16
      { "Input Sequence (Initial)", "ipvs.in_seq.initial", FT_UINT32,
391
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
392
393
16
    { &hf_in_seq_delta,
394
16
      { "Input Sequence (Delta)", "ipvs.in_seq.delta", FT_UINT32,
395
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
396
397
16
    { &hf_in_seq_pdelta,
398
16
      { "Input Sequence (Previous Delta)", "ipvs.in_seq.pdelta", FT_UINT32,
399
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
400
401
16
    { &hf_out_seq_init,
402
16
      { "Output Sequence (Initial)", "ipvs.out_seq.initial", FT_UINT32,
403
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
404
405
16
    { &hf_out_seq_delta,
406
16
      { "Output Sequence (Delta)", "ipvs.out_seq.delta", FT_UINT32,
407
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
408
409
16
    { &hf_out_seq_pdelta,
410
16
      { "Output Sequence (Previous Delta)", "ipvs.out_seq.pdelta", FT_UINT32,
411
16
        BASE_HEX, NULL, 0, NULL, HFILL }},
412
413
    /* v1 payload */
414
415
16
    { &hf_type,
416
16
      { "Type", "ipvs.type", FT_UINT8, BASE_DEC,
417
16
        VALS(type_strings), 0, NULL, HFILL }},
418
419
16
    { &hf_ver,
420
16
      { "Version", "ipvs.ver", FT_UINT16, BASE_DEC,
421
16
        NULL, 0xE000, NULL, HFILL }},
422
423
16
    { &hf_size_v1,
424
16
      { "Size", "ipvs.size.v1", FT_UINT16, BASE_DEC,
425
16
        NULL, 0x1FFF, NULL, HFILL }},
426
427
16
    { &hf_flags_v1,
428
16
      { "Flags", "ipvs.flags.v1", FT_UINT32, BASE_HEX,
429
16
        NULL, 0, NULL, HFILL }},
430
431
16
    { &hf_fwmark,
432
16
      { "FWmark", "ipvs.fwmark", FT_UINT32, BASE_HEX,
433
16
        NULL, 0, NULL, HFILL }},
434
435
16
    { &hf_timeout,
436
16
      { "Timeout", "ipvs.timeout", FT_UINT32, BASE_DEC,
437
16
        NULL, 0, NULL, HFILL }},
438
439
16
    { &hf_caddr6,
440
16
      { "Client Address", "ipvs.caddr6", FT_IPv6, BASE_NONE,
441
16
        NULL, 0, NULL, HFILL }},
442
443
16
    { &hf_vaddr6,
444
16
      { "Virtual Address", "ipvs.vaddr6", FT_IPv6, BASE_NONE,
445
16
        NULL, 0, NULL, HFILL }},
446
447
16
    { &hf_daddr6,
448
16
      { "Destination Address", "ipvs.daddr6", FT_IPv6, BASE_NONE,
449
16
        NULL, 0, NULL, HFILL }},
450
451
16
  };
452
16
  static int *ett[] = {
453
16
    &ett_ipvs_syncd,
454
16
    &ett_conn,
455
16
    &ett_flags,
456
16
  };
457
458
16
  proto_ipvs_syncd = proto_register_protocol("IP Virtual Services Sync Daemon", "IPVS", "ipvs");
459
16
  proto_register_field_array(proto_ipvs_syncd, hf, array_length(hf));
460
16
  proto_register_subtree_array(ett, array_length(ett));
461
462
16
  ipvs_syncd_handle = register_dissector("ipvs", dissect_ipvs_syncd, proto_ipvs_syncd);
463
16
}
464
465
void
466
proto_reg_handoff_ipvs_syncd(void)
467
16
{
468
16
  dissector_add_uint_with_preference("udp.port", IPVS_SYNCD_PORT, ipvs_syncd_handle);
469
16
}
470
471
/*
472
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
473
 *
474
 * Local variables:
475
 * c-basic-offset: 8
476
 * tab-width: 8
477
 * indent-tabs-mode: t
478
 * End:
479
 *
480
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
481
 * :indentSize=8:tabSize=8:noTabs=false:
482
 */