Coverage Report

Created: 2025-02-15 06:25

/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
14
#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
14
#define IP_VS_CONN_F_HASHED           0x0040    /* hashed entry */
97
14
#define IP_VS_CONN_F_NOOUTPUT         0x0080    /* no output packets */
98
14
#define IP_VS_CONN_F_INACTIVE         0x0100    /* not established */
99
14
#define IP_VS_CONN_F_OUT_SEQ          0x0200    /* must do output seq adjust */
100
14
#define IP_VS_CONN_F_IN_SEQ           0x0400    /* must do input seq adjust */
101
67
#define IP_VS_CONN_F_SEQ_MASK         0x0600    /* in/out sequence mask */
102
14
#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
18
{
116
18
  proto_tree *tree;
117
18
  proto_item *item;
118
18
  int         offset = 0;
119
18
  uint8_t     cnt    = 0;
120
18
  uint8_t     version = 0;
121
18
  int         conn   = 0;
122
123
18
  item = proto_tree_add_item(parent_tree, proto_ipvs_syncd, tvb, offset, -1, ENC_NA);
124
18
  tree = proto_item_add_subtree(item, ett_ipvs_syncd);
125
126
127
18
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPVS");
128
18
  col_clear(pinfo->cinfo, COL_INFO);
129
130
18
  cnt = tvb_get_uint8(tvb, offset);
131
18
  if(cnt == 0) { //Version 1 (or after...) first byte is reserved
132
8
    proto_tree_add_item(tree, hf_resv, tvb, offset, 1, ENC_NA);
133
8
    col_set_str(pinfo->cinfo, COL_INFO, "v1");
134
10
  } else {
135
10
    proto_tree_add_item(tree, hf_conn_count, tvb, offset, 1, ENC_BIG_ENDIAN);
136
10
    col_set_str(pinfo->cinfo, COL_INFO, "v0");
137
10
  }
138
18
  offset += 1;
139
140
18
  proto_tree_add_item(tree, hf_syncid, tvb, offset, 1, ENC_BIG_ENDIAN);
141
18
  offset += 1;
142
143
18
  proto_tree_add_item(tree, hf_size, tvb, offset, 2, ENC_BIG_ENDIAN);
144
18
  offset += 2;
145
146
18
  if(cnt == 0) { //Version 1 (or after...)
147
8
    cnt = tvb_get_uint8(tvb, offset);
148
8
    proto_tree_add_item(tree, hf_conn_count, tvb, offset, 1, ENC_BIG_ENDIAN);
149
8
    offset += 1;
150
151
8
    version = tvb_get_uint8(tvb, offset);
152
8
    proto_tree_add_item(tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN);
153
8
    offset += 1;
154
155
8
    proto_tree_add_item(tree, hf_resv, tvb, offset, 2, ENC_NA);
156
8
    offset += 2;
157
8
  }
158
18
  col_append_fstr(pinfo->cinfo, COL_INFO, " %u Connection(s)", cnt);
159
160
117
  for (conn = 0; conn < cnt; conn++)
161
99
  {
162
99
    if(version) {
163
164
32
      proto_tree *ctree;
165
32
      uint8_t type;
166
32
      uint16_t size;
167
168
32
      ctree = proto_tree_add_subtree_format(tree, tvb, offset, 36, ett_conn, NULL,
169
32
                    "Connection #%d", conn+1);
170
171
32
      type = tvb_get_uint8(tvb, offset);
172
32
      proto_tree_add_item(ctree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
173
32
      offset += 1;
174
175
32
      proto_tree_add_item(ctree, hf_proto, tvb, offset, 1, ENC_BIG_ENDIAN);
176
32
      offset += 1;
177
178
32
      size = (tvb_get_ntohs(tvb, offset) & 0x1FFF);
179
32
      proto_item_set_len(ctree, size);
180
32
      proto_tree_add_item(ctree, hf_ver, tvb, offset, 2, ENC_BIG_ENDIAN);
181
32
      proto_tree_add_item(ctree, hf_size_v1, tvb, offset, 2, ENC_BIG_ENDIAN);
182
32
      offset += 2;
183
184
32
      proto_tree_add_item(ctree, hf_flags_v1, tvb, offset, 4, ENC_BIG_ENDIAN);
185
32
      offset += 4;
186
187
32
      proto_tree_add_item(ctree, hf_state, tvb, offset, 2, ENC_BIG_ENDIAN);
188
32
      offset += 2;
189
190
32
      proto_tree_add_item(ctree, hf_cport, tvb, offset, 2, ENC_BIG_ENDIAN);
191
32
      offset += 2;
192
193
32
      proto_tree_add_item(ctree, hf_vport, tvb, offset, 2, ENC_BIG_ENDIAN);
194
32
      offset += 2;
195
196
32
      proto_tree_add_item(ctree, hf_dport, tvb, offset, 2, ENC_BIG_ENDIAN);
197
32
      offset += 2;
198
199
32
      proto_tree_add_item(ctree, hf_fwmark, tvb, offset, 4, ENC_BIG_ENDIAN);
200
32
      offset += 4;
201
202
32
      proto_tree_add_item(ctree, hf_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
203
32
      offset += 4;
204
205
32
      if(type == 0){ /* IPv4 */
206
207
9
        proto_tree_add_item(ctree, hf_caddr, tvb, offset, 4, ENC_BIG_ENDIAN);
208
9
        offset += 4;
209
210
9
        proto_tree_add_item(ctree, hf_vaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
211
9
        offset += 4;
212
213
9
        proto_tree_add_item(ctree, hf_daddr, tvb, offset, 4, ENC_BIG_ENDIAN);
214
9
        offset += 4;
215
23
      } else { /* IPv6 */
216
217
23
        proto_tree_add_item(ctree, hf_caddr6, tvb, offset, 16, ENC_NA);
218
23
        offset += 16;
219
220
23
        proto_tree_add_item(ctree, hf_vaddr6, tvb, offset, 16, ENC_NA);
221
23
        offset += 16;
222
223
23
        proto_tree_add_item(ctree, hf_daddr6, tvb, offset, 16, ENC_NA);
224
23
        offset += 16;
225
23
      }
226
227
67
    } else {
228
229
67
      proto_tree *ctree;
230
67
      proto_tree *ftree, *fi;
231
67
      uint16_t flags;
232
233
67
      ctree = proto_tree_add_subtree_format(tree, tvb, offset, 24, ett_conn, NULL,
234
67
                    "Connection #%d", conn+1);
235
236
67
      proto_tree_add_item(ctree, hf_resv, tvb, offset, 1, ENC_NA);
237
67
      offset += 1;
238
239
67
      proto_tree_add_item(ctree, hf_proto, tvb, offset, 1, ENC_BIG_ENDIAN);
240
67
      offset += 1;
241
242
67
      proto_tree_add_item(ctree, hf_cport, tvb, offset, 2, ENC_BIG_ENDIAN);
243
67
      offset += 2;
244
245
67
      proto_tree_add_item(ctree, hf_vport, tvb, offset, 2, ENC_BIG_ENDIAN);
246
67
      offset += 2;
247
248
67
      proto_tree_add_item(ctree, hf_dport, tvb, offset, 2, ENC_BIG_ENDIAN);
249
67
      offset += 2;
250
251
67
      proto_tree_add_item(ctree, hf_caddr, tvb, offset, 4, ENC_BIG_ENDIAN);
252
67
      offset += 4;
253
254
67
      proto_tree_add_item(ctree, hf_vaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
255
67
      offset += 4;
256
257
67
      proto_tree_add_item(ctree, hf_daddr, tvb, offset, 4, ENC_BIG_ENDIAN);
258
67
      offset += 4;
259
260
67
      flags = tvb_get_ntohs(tvb, offset);
261
67
      fi = proto_tree_add_item(ctree, hf_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
262
67
      ftree = proto_item_add_subtree(fi, ett_flags);
263
67
      proto_tree_add_item(ftree, hf_flags_conn_type, tvb, offset, 2, ENC_BIG_ENDIAN);
264
67
      proto_tree_add_item(ftree, hf_flags_hashed_entry, tvb, offset, 2, ENC_BIG_ENDIAN);
265
67
      proto_tree_add_item(ftree, hf_flags_no_output_packets, tvb, offset, 2, ENC_BIG_ENDIAN);
266
67
      proto_tree_add_item(ftree, hf_flags_conn_not_established, tvb, offset, 2, ENC_BIG_ENDIAN);
267
67
      proto_tree_add_item(ftree, hf_flags_adjust_output_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
268
67
      proto_tree_add_item(ftree, hf_flags_adjust_input_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
269
67
      proto_tree_add_item(ftree, hf_flags_no_client_port_set, tvb, offset, 2, ENC_BIG_ENDIAN);
270
271
67
      offset += 2;
272
273
67
      proto_tree_add_item(ctree, hf_state, tvb, offset, 2, ENC_BIG_ENDIAN);
274
67
      offset += 2;
275
276
      /* we have full connection info */
277
67
      if ( flags & IP_VS_CONN_F_SEQ_MASK )
278
35
      {
279
35
        proto_tree_add_item(ctree, hf_in_seq_init, tvb, offset, 4, ENC_BIG_ENDIAN);
280
35
        offset += 4;
281
282
35
        proto_tree_add_item(ctree, hf_in_seq_delta, tvb, offset, 4, ENC_BIG_ENDIAN);
283
35
        offset += 4;
284
285
35
        proto_tree_add_item(ctree, hf_in_seq_pdelta, tvb, offset, 4, ENC_BIG_ENDIAN);
286
35
        offset += 4;
287
288
35
        proto_tree_add_item(ctree, hf_out_seq_init, tvb, offset, 4, ENC_BIG_ENDIAN);
289
35
        offset += 4;
290
291
35
        proto_tree_add_item(ctree, hf_out_seq_delta, tvb, offset, 4, ENC_BIG_ENDIAN);
292
35
        offset += 4;
293
294
35
        proto_tree_add_item(ctree, hf_out_seq_pdelta, tvb, offset, 4, ENC_BIG_ENDIAN);
295
35
        offset += 4;
296
297
35
      }
298
67
    }
299
300
99
  }
301
302
18
  return tvb_captured_length(tvb);
303
18
}
304
305
void
306
proto_register_ipvs_syncd(void)
307
14
{
308
14
  static hf_register_info hf[] = {
309
14
    { &hf_conn_count,
310
14
      { "Connection Count", "ipvs.conncount", FT_UINT8, BASE_DEC,
311
14
        NULL, 0, NULL, HFILL }},
312
313
14
    { &hf_syncid,
314
14
      { "Synchronization ID", "ipvs.syncid", FT_UINT8, BASE_DEC,
315
14
        NULL, 0, NULL, HFILL }},
316
317
14
    { &hf_size,
318
14
      { "Size", "ipvs.size", FT_UINT16, BASE_DEC,
319
14
        NULL, 0, NULL, HFILL }},
320
321
14
    { &hf_resv,
322
14
      { "Reserved", "ipvs.resv", FT_BYTES, BASE_NONE,
323
14
        NULL, 0, NULL, HFILL }},
324
325
14
    { &hf_version,
326
14
      { "Version", "ipvs.version", FT_UINT8, BASE_DEC,
327
14
        NULL, 0, NULL, HFILL }},
328
329
14
    { &hf_proto,
330
14
      { "Protocol", "ipvs.proto", FT_UINT8, BASE_HEX,
331
14
        VALS(proto_strings), 0, NULL, HFILL }},
332
333
14
    { &hf_cport,
334
14
      { "Client Port", "ipvs.cport", FT_UINT16, BASE_DEC,
335
14
        NULL, 0, NULL, HFILL }},
336
337
14
    { &hf_vport,
338
14
      { "Virtual Port", "ipvs.vport", FT_UINT16, BASE_DEC,
339
14
        NULL, 0, NULL, HFILL }},
340
341
14
    { &hf_dport,
342
14
      { "Destination Port", "ipvs.dport", FT_UINT16, BASE_DEC,
343
14
        NULL, 0, NULL, HFILL }},
344
345
14
    { &hf_caddr,
346
14
      { "Client Address", "ipvs.caddr", FT_IPv4, BASE_NONE,
347
14
        NULL, 0, NULL, HFILL }},
348
349
14
    { &hf_vaddr,
350
14
      { "Virtual Address", "ipvs.vaddr", FT_IPv4, BASE_NONE,
351
14
        NULL, 0, NULL, HFILL }},
352
353
14
    { &hf_daddr,
354
14
      { "Destination Address", "ipvs.daddr", FT_IPv4, BASE_NONE,
355
14
        NULL, 0, NULL, HFILL }},
356
357
14
    { &hf_flags,
358
14
      { "Flags", "ipvs.flags", FT_UINT16, BASE_HEX,
359
14
        NULL, 0, NULL, HFILL }},
360
361
14
    { &hf_flags_conn_type,
362
14
      { "Connection Type", "ipvs.flags.conn_type", FT_UINT16, BASE_HEX,
363
14
        VALS(connection_type_strings), 0x0F, NULL, HFILL }},
364
365
14
    { &hf_flags_hashed_entry,
366
14
      { "Hashed Entry", "ipvs.flags.hashed_entry", FT_BOOLEAN, 16,
367
14
        NULL, IP_VS_CONN_F_HASHED, NULL, HFILL }},
368
369
14
    { &hf_flags_no_output_packets,
370
14
      { "No Output Packets", "ipvs.flags.no_output_packets", FT_BOOLEAN, 16,
371
14
        NULL, IP_VS_CONN_F_NOOUTPUT, NULL, HFILL }},
372
373
14
    { &hf_flags_conn_not_established,
374
14
      { "Connection Not Established", "ipvs.flags.conn_not_established", FT_BOOLEAN, 16,
375
14
        NULL, IP_VS_CONN_F_INACTIVE, NULL, HFILL }},
376
377
14
    { &hf_flags_adjust_output_seq,
378
14
      { "Adjust Output Sequence", "ipvs.flags.adjust_output_seq", FT_BOOLEAN, 16,
379
14
        NULL, IP_VS_CONN_F_OUT_SEQ, NULL, HFILL }},
380
381
14
    { &hf_flags_adjust_input_seq,
382
14
      { "Adjust Input Sequence", "ipvs.flags.adjust_input_seq", FT_BOOLEAN, 16,
383
14
        NULL, IP_VS_CONN_F_IN_SEQ, NULL, HFILL }},
384
385
14
    { &hf_flags_no_client_port_set,
386
14
      { "No Client Port Set", "ipvs.flags.no_client_port_set", FT_BOOLEAN, 16,
387
14
        NULL, IP_VS_CONN_F_NO_CPORT, NULL, HFILL }},
388
389
14
    { &hf_state,
390
14
      { "State", "ipvs.state", FT_UINT16, BASE_HEX,
391
14
        VALS(state_strings), 0, NULL, HFILL }},
392
393
14
    { &hf_in_seq_init,
394
14
      { "Input Sequence (Initial)", "ipvs.in_seq.initial", FT_UINT32,
395
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
396
397
14
    { &hf_in_seq_delta,
398
14
      { "Input Sequence (Delta)", "ipvs.in_seq.delta", FT_UINT32,
399
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
400
401
14
    { &hf_in_seq_pdelta,
402
14
      { "Input Sequence (Previous Delta)", "ipvs.in_seq.pdelta", FT_UINT32,
403
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
404
405
14
    { &hf_out_seq_init,
406
14
      { "Output Sequence (Initial)", "ipvs.out_seq.initial", FT_UINT32,
407
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
408
409
14
    { &hf_out_seq_delta,
410
14
      { "Output Sequence (Delta)", "ipvs.out_seq.delta", FT_UINT32,
411
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
412
413
14
    { &hf_out_seq_pdelta,
414
14
      { "Output Sequence (Previous Delta)", "ipvs.out_seq.pdelta", FT_UINT32,
415
14
        BASE_HEX, NULL, 0, NULL, HFILL }},
416
417
    /* v1 payload */
418
419
14
    { &hf_type,
420
14
      { "Type", "ipvs.type", FT_UINT8, BASE_DEC,
421
14
        VALS(type_strings), 0, NULL, HFILL }},
422
423
14
    { &hf_ver,
424
14
      { "Version", "ipvs.ver", FT_UINT16, BASE_DEC,
425
14
        NULL, 0xE000, NULL, HFILL }},
426
427
14
    { &hf_size_v1,
428
14
      { "Size", "ipvs.size.v1", FT_UINT16, BASE_DEC,
429
14
        NULL, 0x1FFF, NULL, HFILL }},
430
431
14
    { &hf_flags_v1,
432
14
      { "Flags", "ipvs.flags.v1", FT_UINT32, BASE_HEX,
433
14
        NULL, 0, NULL, HFILL }},
434
435
14
    { &hf_fwmark,
436
14
      { "FWmark", "ipvs.fwmark", FT_UINT32, BASE_HEX,
437
14
        NULL, 0, NULL, HFILL }},
438
439
14
    { &hf_timeout,
440
14
      { "Timeout", "ipvs.timeout", FT_UINT32, BASE_DEC,
441
14
        NULL, 0, NULL, HFILL }},
442
443
14
    { &hf_caddr6,
444
14
      { "Client Address", "ipvs.caddr6", FT_IPv6, BASE_NONE,
445
14
        NULL, 0, NULL, HFILL }},
446
447
14
    { &hf_vaddr6,
448
14
      { "Virtual Address", "ipvs.vaddr6", FT_IPv6, BASE_NONE,
449
14
        NULL, 0, NULL, HFILL }},
450
451
14
    { &hf_daddr6,
452
14
      { "Destination Address", "ipvs.daddr6", FT_IPv6, BASE_NONE,
453
14
        NULL, 0, NULL, HFILL }},
454
455
14
  };
456
14
  static int *ett[] = {
457
14
    &ett_ipvs_syncd,
458
14
    &ett_conn,
459
14
    &ett_flags,
460
14
  };
461
462
14
  proto_ipvs_syncd = proto_register_protocol("IP Virtual Services Sync Daemon", "IPVS", "ipvs");
463
14
  proto_register_field_array(proto_ipvs_syncd, hf, array_length(hf));
464
14
  proto_register_subtree_array(ett, array_length(ett));
465
466
14
  ipvs_syncd_handle = register_dissector("ipvs", dissect_ipvs_syncd, proto_ipvs_syncd);
467
14
}
468
469
void
470
proto_reg_handoff_ipvs_syncd(void)
471
14
{
472
14
  dissector_add_uint_with_preference("udp.port", IPVS_SYNCD_PORT, ipvs_syncd_handle);
473
14
}
474
475
/*
476
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
477
 *
478
 * Local variables:
479
 * c-basic-offset: 8
480
 * tab-width: 8
481
 * indent-tabs-mode: t
482
 * End:
483
 *
484
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
485
 * :indentSize=8:tabSize=8:noTabs=false:
486
 */