Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lsd.c
blobac4cfa4d40c0553ba9b0e66c400f20923f07d6fc
1 /* packet-lsd.c
2 * Local Service Discovery packet dissector
4 * From http://bittorrent.org/beps/bep_0014.html
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include <epan/strutil.h>
18 #include <wsutil/pint.h>
19 #include <wsutil/strtoi.h>
21 void proto_register_lsd(void);
22 void proto_reg_handoff_lsd(void);
24 #define LSD_MULTICAST_ADDRESS 0xEFC0988F /* 239.192.152.143 */
25 #define LSD_PORT 6771
27 static int proto_lsd;
28 static int hf_lsd_header;
29 static int hf_lsd_host;
30 static int hf_lsd_port;
31 static int hf_lsd_infohash;
32 static int hf_lsd_cookie;
34 static int ett_lsd;
36 static expert_field ei_lsd_field;
38 static bool
39 parse_string_field(proto_tree *tree, int hf, packet_info *pinfo, tvbuff_t *tvb, int offset, int* next_offset, int* linelen)
41 uint8_t *str;
42 header_field_info* hf_info = proto_registrar_get_nth(hf);
43 char **field_and_value;
44 proto_item* ti;
45 char *p;
47 *linelen = tvb_find_line_end(tvb, offset, -1, next_offset, false);
48 if (*linelen < 0)
49 return false;
51 str = tvb_get_string_enc(pinfo->pool, tvb, offset, *linelen, ENC_ASCII);
52 if (g_ascii_strncasecmp(str, hf_info->name, strlen(hf_info->name)) == 0)
54 field_and_value = wmem_strsplit(pinfo->pool, str, ":", 2);
55 p = field_and_value[1];
56 if (p) {
57 while(g_ascii_isspace(*p))
58 p++;
59 proto_tree_add_string(tree, hf, tvb, offset, *linelen, p);
60 return true;
63 ti = proto_tree_add_string_format(tree, hf, tvb, offset, *linelen, str, "%s", str);
64 expert_add_info_format(pinfo, ti, &ei_lsd_field, "%s field malformed", hf_info->name);
66 return true;
69 static int
70 dissect_lsd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
72 proto_item *ti = NULL;
73 proto_tree *lsd_tree;
74 int offset = 0, next_offset = 0, linelen;
75 uint8_t *str;
76 char **field_and_value;
77 uint16_t port;
78 bool valid;
80 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, false);
81 if (linelen < 0)
82 return 0;
84 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSD");
85 col_clear(pinfo->cinfo, COL_INFO);
87 /* Create display subtree for the protocol */
88 ti = proto_tree_add_item(tree, proto_lsd, tvb, 0, -1, ENC_NA);
89 lsd_tree = proto_item_add_subtree(ti, ett_lsd);
91 proto_tree_add_item(lsd_tree, hf_lsd_header, tvb, offset, linelen, ENC_ASCII);
93 offset = next_offset;
94 if (!parse_string_field(lsd_tree, hf_lsd_host, pinfo, tvb, offset, &next_offset, &linelen))
95 return offset+linelen;
97 offset = next_offset;
98 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, false);
99 if (linelen < 0)
100 return offset+linelen;
101 str = tvb_get_string_enc(pinfo->pool, tvb, offset, linelen, ENC_ASCII);
102 if (g_ascii_strncasecmp(str, "Port", strlen("Port")) == 0)
104 field_and_value = wmem_strsplit(pinfo->pool, str, ":", 2);
105 valid = ws_strtou16(field_and_value[1], NULL, &port);
106 ti = proto_tree_add_uint(lsd_tree, hf_lsd_port, tvb, offset, linelen, port);
107 if (!valid)
109 expert_add_info_format(pinfo, ti, &ei_lsd_field, "Port value malformed");
112 else
114 ti = proto_tree_add_uint(lsd_tree, hf_lsd_port, tvb, offset, 0, 0xFFFF);
115 expert_add_info_format(pinfo, ti, &ei_lsd_field, "Port field malformed");
117 proto_item_set_len(ti, linelen);
119 offset = next_offset;
120 if (!parse_string_field(lsd_tree, hf_lsd_infohash, pinfo, tvb, offset, &next_offset, &linelen))
121 return offset+linelen;
123 offset = next_offset;
124 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, false);
125 if (linelen < 0)
126 return offset+linelen;
127 /* Cookie is optional */
128 if (tvb_strncaseeql(tvb, offset, "cookie", strlen("cookie")) == 0)
130 if (!parse_string_field(lsd_tree, hf_lsd_cookie, pinfo, tvb, offset, &next_offset, &linelen))
131 return offset+linelen;
134 return tvb_captured_length(tvb);
137 static bool
138 dissect_lsd_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
140 if (pinfo->dst.type == AT_IPv4 && pntoh32(pinfo->dst.data) == LSD_MULTICAST_ADDRESS && pinfo->destport == LSD_PORT)
141 return (dissect_lsd(tvb, pinfo, tree, data) != 0);
143 if (pinfo->dst.type == AT_IPv6 && pinfo->destport == LSD_PORT)
144 return (dissect_lsd(tvb, pinfo, tree, data) != 0);
146 return false;
149 void
150 proto_register_lsd(void)
152 static hf_register_info hf[] = {
153 { &hf_lsd_header,
154 { "Header", "lsd.header",
155 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
157 { &hf_lsd_host,
158 { "Host", "lsd.host",
159 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
161 { &hf_lsd_port,
162 { "Port", "lsd.port",
163 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
165 { &hf_lsd_infohash,
166 { "Infohash", "lsd.infohash",
167 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
169 { &hf_lsd_cookie,
170 { "cookie", "lsd.cookie",
171 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
175 static int *ett[] = {
176 &ett_lsd,
179 static ei_register_info ei[] = {
180 { &ei_lsd_field, { "lsd.malformed_field", PI_MALFORMED, PI_ERROR, "Malformed LDS field", EXPFILL }},
183 expert_module_t* expert_lsd;
185 proto_lsd = proto_register_protocol("Local Service Discovery", "LSD", "lsd");
187 proto_register_field_array(proto_lsd, hf, array_length(hf));
188 proto_register_subtree_array(ett, array_length(ett));
189 expert_lsd = expert_register_protocol(proto_lsd);
190 expert_register_field_array(expert_lsd, ei, array_length(ei));
193 void
194 proto_reg_handoff_lsd(void)
196 heur_dissector_add( "udp", dissect_lsd_heur, "LSD over UDP", "lsd_udp", proto_lsd, HEURISTIC_ENABLE);
200 * Editor modelines - https://www.wireshark.org/tools/modelines.html
202 * Local Variables:
203 * c-basic-offset: 2
204 * tab-width: 8
205 * indent-tabs-mode: nil
206 * End:
208 * ex: set shiftwidth=2 tabstop=8 expandtab:
209 * :indentSize=2:tabSize=8:noTabs=true: