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-tsdns.c
Line
Count
Source
1
/* packet-tsdns.c
2
 * Routines for TSDNS (TeamSpeak3 DNS) packet disassembly
3
 * Copyright 2018, Maciej Krueger <mkg20001@gmail.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/expert.h>
16
#include <epan/strutil.h>
17
#include <wsutil/strtoi.h>
18
19
#define TSDNS_PORT  41144   /* Not IANA registered */
20
21
void proto_register_tsdns(void);
22
void proto_reg_handoff_tsdns(void);
23
static dissector_handle_t tsdns_handle;
24
25
static int proto_tsdns;
26
27
static int hf_tsdns_data;
28
static int hf_tsdns_request;
29
static int hf_tsdns_request_domain;
30
static int hf_tsdns_response;
31
static int hf_tsdns_response_ip;
32
static int hf_tsdns_response_address;
33
static int hf_tsdns_response_port;
34
35
static expert_field ei_response_port_malformed;
36
37
static int ett_tsdns;
38
39
static int dissect_tsdns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
40
0
{
41
42
0
  int         offset    = 0;
43
0
  bool        request   = false;
44
45
0
  if (pinfo->destport == pinfo->match_uint) {
46
0
    request = true;
47
0
  }
48
49
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "TSDNS");
50
51
0
  int pLen = tvb_reported_length(tvb);
52
53
0
  if (request) {
54
0
    col_set_str(pinfo->cinfo, COL_INFO, "Request");
55
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tvb_get_string_enc(pinfo->pool, tvb, 0, pLen - 5, ENC_ASCII));
56
0
  } else {
57
0
    col_set_str(pinfo->cinfo, COL_INFO, "Response");
58
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tvb_get_string_enc(pinfo->pool, tvb, 0, pLen, ENC_ASCII));
59
0
  }
60
61
0
  proto_tree *tsdns_tree;
62
0
  proto_item *ti, *hidden_item, *address_item;
63
64
0
  ti = proto_tree_add_item(tree, proto_tsdns, tvb, offset, -1, ENC_NA);
65
0
  tsdns_tree = proto_item_add_subtree(ti, ett_tsdns);
66
67
0
  hidden_item = proto_tree_add_item(tsdns_tree, hf_tsdns_data, tvb, offset, -1, ENC_ASCII);
68
0
  proto_item_set_hidden(hidden_item);
69
70
0
  if (request) { // request is DOMAIN\n\r\r\r\n
71
0
    hidden_item = proto_tree_add_boolean(tsdns_tree, hf_tsdns_request, tvb, 0, 0, 1); // using pLen - 5 as the last chars are \n\r\r\r\n which are just indicating the end of the request
72
0
    proto_tree_add_item(tsdns_tree, hf_tsdns_request_domain, tvb, offset, pLen - 5, ENC_ASCII);
73
0
  } else { // response is IP:PORT
74
0
    hidden_item = proto_tree_add_boolean(tsdns_tree, hf_tsdns_response, tvb, 0, 0, 1);
75
0
    address_item = proto_tree_add_item(tsdns_tree, hf_tsdns_response_address, tvb, offset, pLen, ENC_ASCII);
76
0
    char** splitAddress;
77
0
    splitAddress = wmem_strsplit(pinfo->pool, tvb_format_text(pinfo->pool, tvb, 0, pLen), ":", 1); // unsure if TSDNS also does IPv6...
78
0
    if (splitAddress == NULL || splitAddress[0] == NULL || splitAddress[1] == NULL) {
79
0
      expert_add_info(pinfo, address_item, &ei_response_port_malformed);
80
0
    } else {
81
0
      proto_tree_add_string(tsdns_tree, hf_tsdns_response_ip, tvb, 0, pLen, splitAddress[0]);
82
0
      uint32_t port;
83
0
      if (ws_strtou32(splitAddress[1], NULL, &port))
84
0
        proto_tree_add_uint(tsdns_tree, hf_tsdns_response_port, tvb, 0, pLen, port);
85
0
    }
86
0
  }
87
0
  proto_item_set_hidden(hidden_item);
88
89
0
  return tvb_captured_length(tvb);
90
91
0
} /* dissect_tsdns */
92
93
void proto_register_tsdns(void)
94
16
{
95
96
16
  static hf_register_info hf[] = {
97
16
    { &hf_tsdns_data,
98
16
      { "Data",    "tsdns.data",
99
16
        FT_STRING,       BASE_NONE,      NULL,   0x0,
100
16
        NULL, HFILL }},
101
16
    { &hf_tsdns_request,
102
16
      { "Request", "tsdns.request",
103
16
        FT_BOOLEAN,     BASE_NONE,      NULL,   0x0,
104
16
        "true if TSDNS Request", HFILL }},
105
16
    { &hf_tsdns_request_domain,
106
16
      { "Requested Domain", "tsdns.request.domain",
107
16
        FT_STRING,     BASE_NONE,      NULL,   0x0,
108
16
        NULL, HFILL }},
109
16
    { &hf_tsdns_response,
110
16
      { "Response","tsdns.response",
111
16
        FT_BOOLEAN,     BASE_NONE,      NULL,   0x0,
112
16
        "true if TSDNS Response", HFILL }},
113
16
    { &hf_tsdns_response_address,
114
16
       { "Response Address","tsdns.response.address",
115
16
         FT_STRING,     BASE_NONE,      NULL,   0x0,
116
16
         NULL, HFILL }},
117
16
    { &hf_tsdns_response_ip,
118
16
      { "Response IP","tsdns.response.ip",
119
16
        FT_STRING,     BASE_NONE,      NULL,   0x0,
120
16
        NULL, HFILL }},
121
16
    { &hf_tsdns_response_port,
122
16
      { "Response Port","tsdns.response.port",
123
16
        FT_UINT16,     BASE_DEC,      NULL,   0x0,
124
16
        NULL, HFILL }}
125
16
  };
126
127
16
  static ei_register_info ei[] = {
128
16
          { &ei_response_port_malformed, { "tsdns.response.port.malformed", PI_MALFORMED, PI_ERROR, "Address port is not an integer or not contained in address", EXPFILL }}
129
16
  };
130
16
  expert_module_t* expert_tsdns;
131
132
16
  static int *ett[] = {
133
16
    &ett_tsdns
134
16
  };
135
136
16
  proto_tsdns = proto_register_protocol("TeamSpeak3 DNS", "TSDNS", "tsdns");
137
16
  proto_register_field_array(proto_tsdns, hf, array_length(hf));
138
16
  proto_register_subtree_array(ett, array_length(ett));
139
16
  expert_tsdns = expert_register_protocol(proto_tsdns);
140
16
  expert_register_field_array(expert_tsdns, ei, array_length(ei));
141
142
16
  tsdns_handle = register_dissector("tsdns", dissect_tsdns, proto_tsdns);
143
16
}
144
145
void proto_reg_handoff_tsdns(void)
146
16
{
147
  /* Default port to not dissect the protocol*/
148
16
  dissector_add_uint_with_preference("tcp.port", 0, tsdns_handle);
149
16
}
150
151
/*
152
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
153
 *
154
 * Local variables:
155
 * c-basic-offset: 2
156
 * tab-width: 8
157
 * indent-tabs-mode: t
158
 * End:
159
 *
160
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
161
 * :indentSize=8:tabSize=8:noTabs=false:
162
 */