/src/wireshark/epan/dissectors/packet-lsdp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-lsdp.c |
2 | | * Dissector for Lenbrook Service Discovery Protocol |
3 | | * |
4 | | * Copyright (c) 2024 by Martin Mayer <martin.mayer@m2-it-solutions.de> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | #include <epan/packet.h> |
15 | | #include <epan/expert.h> |
16 | | #include <wsutil/str_util.h> |
17 | | |
18 | 14 | #define LSDP_UDP_PORT 11430 |
19 | 0 | #define LSDP_HEADER_LEN 6 |
20 | 0 | #define LSDP_HEADER_VER 1 |
21 | 0 | #define LSDP_MAGIC "LSDP" |
22 | | |
23 | | void proto_register_lsdp(void); |
24 | | void proto_reg_handoff_lsdp(void); |
25 | | |
26 | | static dissector_handle_t lsdp_handle; |
27 | | |
28 | | static int proto_lsdp; |
29 | | |
30 | | /* Header Fields */ |
31 | | static int hf_lsdp_header_length; |
32 | | static int hf_lsdp_header_magic_word; |
33 | | static int hf_lsdp_header_proto_version; |
34 | | |
35 | | /* Common Message Fields */ |
36 | | static int hf_lsdp_msg_length; |
37 | | static int hf_lsdp_msg_type; |
38 | | static int hf_lsdp_node_id_length; |
39 | | static int hf_lsdp_node_id_mac; |
40 | | static int hf_lsdp_node_id; |
41 | | |
42 | | /* Query Message */ |
43 | | static int hf_lsdp_query; |
44 | | static int hf_lsdp_query_count; |
45 | | static int hf_lsdp_query_class; |
46 | | |
47 | | /* Announce Message */ |
48 | | static int hf_lsdp_announce; |
49 | | static int hf_lsdp_announce_addr_length; |
50 | | static int hf_lsdp_announce_addr_ipv4; |
51 | | static int hf_lsdp_announce_addr_ipv6; |
52 | | static int hf_lsdp_announce_count; |
53 | | |
54 | | /* Announce Message Records */ |
55 | | static int hf_lsdp_announce_record; |
56 | | static int hf_lsdp_announce_record_class; |
57 | | static int hf_lsdp_announce_record_count; |
58 | | |
59 | | /* Announce Message Record TXT-Records */ |
60 | | static int hf_lsdp_announce_record_txt; |
61 | | static int hf_lsdp_announce_record_txt_key_length; |
62 | | static int hf_lsdp_announce_record_txt_key; |
63 | | static int hf_lsdp_announce_record_txt_value_length; |
64 | | static int hf_lsdp_announce_record_txt_value; |
65 | | |
66 | | /* Delete Message */ |
67 | | static int hf_lsdp_delete; |
68 | | static int hf_lsdp_delete_count; |
69 | | static int hf_lsdp_delete_class; |
70 | | |
71 | | /* Trees */ |
72 | | static int ett_lsdp; |
73 | | static int ett_lsdp_node_id; |
74 | | static int ett_lsdp_msg; |
75 | | static int ett_lsdp_msg_rec; |
76 | | static int ett_lsdp_msg_rec_txt; |
77 | | |
78 | | /* Expert fields */ |
79 | | static expert_field ei_lsdp_unknown_msg_type; |
80 | | static expert_field ei_lsdp_invalid_addr_len; |
81 | | |
82 | | #define CLASS_PLAYER 0x0001 |
83 | | #define CLASS_SERVER 0x0002 |
84 | | #define CLASS_PLAYER_MZ 0x0003 |
85 | | #define CLASS_SOVI_MFG 0x0004 |
86 | | #define CLASS_SOVI_KEYPAD 0x0005 |
87 | | #define CLASS_PLAYER_SLAVE 0x0006 |
88 | | #define CLASS_REMOTE_APP 0x0007 |
89 | | #define CLASS_HUB 0x0008 |
90 | | #define CLASS_ALL 0xFFFF |
91 | | |
92 | | static const value_string lsdp_class_id_vals[] = { |
93 | | { CLASS_PLAYER, "BluOS Player" }, |
94 | | { CLASS_SERVER, "BluOS Server" }, |
95 | | { CLASS_PLAYER_MZ, "BluOS Player (secondary in multi-zone)" }, |
96 | | { CLASS_SOVI_MFG, "sovi-mfg (used for manufacturing testing)" }, |
97 | | { CLASS_SOVI_KEYPAD, "sovi-keypad" }, |
98 | | { CLASS_PLAYER_SLAVE, "BluOS Player (pair slave)" }, |
99 | | { CLASS_REMOTE_APP, "Remote Web App (AVR OSD Web Page)" }, |
100 | | { CLASS_HUB, "BluOS Hub" }, |
101 | | { CLASS_ALL, "All Classes (Query Message)" }, |
102 | | { 0, NULL } |
103 | | }; |
104 | | |
105 | | static const value_string lsdp_class_id_short_vals[] = { |
106 | | { CLASS_PLAYER, "Player" }, |
107 | | { CLASS_SERVER, "Server" }, |
108 | | { CLASS_PLAYER_MZ, "Multizone Player" }, |
109 | | { CLASS_SOVI_MFG, "sovi-mfg" }, |
110 | | { CLASS_SOVI_KEYPAD, "sovi-keypad" }, |
111 | | { CLASS_PLAYER_SLAVE, "Slave Player" }, |
112 | | { CLASS_REMOTE_APP, "Web App" }, |
113 | | { CLASS_HUB, "Hub" }, |
114 | | { CLASS_ALL, "All Classes" }, |
115 | | { 0, NULL } |
116 | | }; |
117 | | |
118 | 0 | #define MSG_TYPE_ANNOUNCE 0x41 // Chr. 'A' |
119 | 0 | #define MSG_TYPE_DELETE 0x44 // Chr. 'D' |
120 | 0 | #define MSG_TYPE_QUERY_BCR 0x51 // Chr. 'Q' |
121 | 0 | #define MSG_TYPE_QUERY_UCR 0x52 // Chr. 'R' |
122 | | |
123 | | static const value_string lsdp_msg_type_vals[] = { |
124 | | { MSG_TYPE_ANNOUNCE, "Announce Message" }, |
125 | | { MSG_TYPE_DELETE, "Delete Message" }, |
126 | | { MSG_TYPE_QUERY_BCR, "Query Message (for broadcast response)" }, |
127 | | { MSG_TYPE_QUERY_UCR, "Query Message (for unicast response)" }, |
128 | | { 0, NULL } |
129 | | }; |
130 | | |
131 | | static int |
132 | | dissect_lsdp_node_info(tvbuff_t *tvb, proto_tree *tree, int offset) |
133 | 0 | { |
134 | 0 | uint8_t node_id_len; |
135 | 0 | int start_offset = offset; |
136 | 0 | proto_item *pi_id; |
137 | 0 | proto_tree *id_tree; |
138 | |
|
139 | 0 | node_id_len = tvb_get_uint8(tvb, offset); |
140 | 0 | proto_tree_add_item(tree, hf_lsdp_node_id_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
141 | 0 | offset += 1; |
142 | | |
143 | | /* |
144 | | Normally, Node-ID is the MAC address of an interface, but COULD also be an arbitrary ID. |
145 | | Populate Node-ID field and also MAC if length is 6. |
146 | | */ |
147 | 0 | pi_id = proto_tree_add_item(tree, hf_lsdp_node_id, tvb, offset, node_id_len, ENC_NA); |
148 | 0 | if(node_id_len == 6) { |
149 | 0 | id_tree = proto_item_add_subtree(pi_id, ett_lsdp_node_id); |
150 | 0 | proto_tree_add_item(id_tree, hf_lsdp_node_id_mac, tvb, offset, node_id_len, ENC_NA); |
151 | 0 | } |
152 | 0 | offset += node_id_len; |
153 | |
|
154 | 0 | return offset - start_offset; |
155 | 0 | } |
156 | | |
157 | | static int |
158 | | dissect_lsdp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) |
159 | 0 | { |
160 | 0 | uint8_t msg_type, msg_len; |
161 | 0 | uint32_t addr_len, count, txt_count, k_len, v_len, class; |
162 | 0 | int offset_s1, offset_s2; |
163 | 0 | proto_item *msg_item, *rec_item, *txt_item; |
164 | 0 | proto_tree *msg_tree, *rec_tree, *txt_tree; |
165 | 0 | const uint8_t *key, *val; |
166 | |
|
167 | 0 | msg_len = tvb_get_uint8(tvb, offset); |
168 | 0 | msg_type = tvb_get_uint8(tvb, offset+1); |
169 | |
|
170 | 0 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(msg_type, lsdp_msg_type_vals, "Unknown Message Type")); |
171 | |
|
172 | 0 | switch (msg_type) { |
173 | 0 | case MSG_TYPE_QUERY_BCR: |
174 | 0 | case MSG_TYPE_QUERY_UCR: |
175 | |
|
176 | 0 | msg_item = proto_tree_add_item(tree, hf_lsdp_query, tvb, offset, msg_len, ENC_NA); |
177 | 0 | msg_tree = proto_item_add_subtree(msg_item, ett_lsdp_msg); |
178 | |
|
179 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
180 | 0 | offset += 1; |
181 | |
|
182 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
183 | 0 | offset += 1; |
184 | |
|
185 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_query_count, tvb, offset, 1, ENC_BIG_ENDIAN, &count); |
186 | 0 | offset += 1; |
187 | |
|
188 | 0 | for(uint32_t i=0; i < count; i++) { |
189 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_query_class, tvb, offset, 2, ENC_BIG_ENDIAN, &class); |
190 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", val_to_str_const(class, lsdp_class_id_short_vals, "Unknown Class")); |
191 | 0 | offset += 2; |
192 | 0 | } |
193 | |
|
194 | 0 | break; |
195 | | |
196 | 0 | case MSG_TYPE_ANNOUNCE: |
197 | |
|
198 | 0 | msg_item = proto_tree_add_item(tree, hf_lsdp_announce, tvb, offset, msg_len, ENC_NA); |
199 | 0 | msg_tree = proto_item_add_subtree(msg_item, ett_lsdp_msg); |
200 | |
|
201 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
202 | 0 | offset += 1; |
203 | |
|
204 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
205 | 0 | offset += 1; |
206 | |
|
207 | 0 | offset += dissect_lsdp_node_info(tvb, msg_tree, offset); |
208 | |
|
209 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_announce_addr_length, tvb, offset, 1, ENC_BIG_ENDIAN, &addr_len); |
210 | 0 | offset += 1; |
211 | |
|
212 | 0 | if(addr_len == 4) { |
213 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_announce_addr_ipv4, tvb, offset, addr_len, ENC_NA); |
214 | 0 | } else if (addr_len==16) { |
215 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_announce_addr_ipv6, tvb, offset, addr_len, ENC_NA); |
216 | 0 | } else { |
217 | 0 | expert_add_info(pinfo, msg_tree, &ei_lsdp_invalid_addr_len); |
218 | 0 | } |
219 | 0 | offset += addr_len; |
220 | |
|
221 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_announce_count, tvb, offset, 1, ENC_BIG_ENDIAN, &count); |
222 | 0 | proto_item_append_text(msg_item, " (%d Record%s)", count, plurality(count, "", "s")); |
223 | 0 | offset += 1; |
224 | | |
225 | | /* Loop Announce Records */ |
226 | 0 | for(uint32_t i=0; i < count; i++) { |
227 | |
|
228 | 0 | offset_s1 = offset; |
229 | |
|
230 | 0 | rec_item = proto_tree_add_item(msg_tree, hf_lsdp_announce_record, tvb, offset, 0, ENC_NA); |
231 | 0 | rec_tree = proto_item_add_subtree(rec_item, ett_lsdp_msg_rec); |
232 | |
|
233 | 0 | proto_tree_add_item_ret_uint(rec_tree, hf_lsdp_announce_record_class, tvb, offset, 2, ENC_BIG_ENDIAN, &class); |
234 | 0 | offset += 2; |
235 | |
|
236 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", val_to_str_const(class, lsdp_class_id_short_vals, "Unknown Class")); |
237 | |
|
238 | 0 | proto_tree_add_item_ret_uint(rec_tree, hf_lsdp_announce_record_count, tvb, offset, 1, ENC_BIG_ENDIAN, &txt_count); |
239 | 0 | proto_item_append_text(rec_item, " (%d TXT-Record%s)", txt_count, plurality(txt_count, "", "s")); |
240 | 0 | offset += 1; |
241 | | |
242 | | /* Loop TXT records (key-value pairs) */ |
243 | 0 | for(uint32_t j=0; j < txt_count; j++) { |
244 | |
|
245 | 0 | offset_s2 = offset; |
246 | |
|
247 | 0 | txt_item = proto_tree_add_item(rec_tree, hf_lsdp_announce_record_txt, tvb, offset, 0, ENC_NA); |
248 | 0 | txt_tree = proto_item_add_subtree(txt_item, ett_lsdp_msg_rec_txt); |
249 | |
|
250 | 0 | proto_tree_add_item_ret_uint(txt_tree, hf_lsdp_announce_record_txt_key_length, tvb, offset, 1, ENC_BIG_ENDIAN, &k_len); |
251 | 0 | offset += 1; |
252 | |
|
253 | 0 | proto_tree_add_item_ret_string(txt_tree, hf_lsdp_announce_record_txt_key, tvb, offset, k_len, ENC_UTF_8, pinfo->pool, &key); |
254 | 0 | offset += k_len; |
255 | |
|
256 | 0 | proto_tree_add_item_ret_uint(txt_tree, hf_lsdp_announce_record_txt_value_length, tvb, offset, 1, ENC_BIG_ENDIAN, &v_len); |
257 | 0 | offset += 1; |
258 | |
|
259 | 0 | proto_tree_add_item_ret_string(txt_tree, hf_lsdp_announce_record_txt_value, tvb, offset, v_len, ENC_UTF_8, pinfo->pool, &val); |
260 | 0 | offset += v_len; |
261 | |
|
262 | 0 | proto_item_append_text(txt_item, " (%s: %s)", key, val); |
263 | 0 | proto_item_set_len(txt_item, offset - offset_s2); |
264 | | |
265 | | /* Keys of interest for info column */ |
266 | 0 | if( |
267 | 0 | strcmp(key, "name") == 0 || |
268 | 0 | strcmp(key, "model") == 0 || |
269 | 0 | strcmp(key, "version") == 0 |
270 | 0 | ) { |
271 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s='%s'", key, val); |
272 | 0 | } |
273 | 0 | } |
274 | |
|
275 | 0 | proto_item_set_len(rec_item, offset - offset_s1); |
276 | 0 | } |
277 | |
|
278 | 0 | break; |
279 | | |
280 | 0 | case MSG_TYPE_DELETE: |
281 | |
|
282 | 0 | msg_item = proto_tree_add_item(tree, hf_lsdp_delete, tvb, offset, msg_len, ENC_NA); |
283 | 0 | msg_tree = proto_item_add_subtree(msg_item, ett_lsdp_msg); |
284 | |
|
285 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
286 | 0 | offset += 1; |
287 | |
|
288 | 0 | proto_tree_add_item(msg_tree, hf_lsdp_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
289 | 0 | offset += 1; |
290 | |
|
291 | 0 | offset += dissect_lsdp_node_info(tvb, msg_tree, offset); |
292 | |
|
293 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_delete_count, tvb, offset, 1, ENC_BIG_ENDIAN, &count); |
294 | 0 | offset += 1; |
295 | |
|
296 | 0 | for(uint32_t i=0; i < count; i++) { |
297 | 0 | proto_tree_add_item_ret_uint(msg_tree, hf_lsdp_delete_class, tvb, offset, 2, ENC_BIG_ENDIAN, &class); |
298 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", val_to_str_const(class, lsdp_class_id_short_vals, "Unknown Class")); |
299 | 0 | offset += 2; |
300 | 0 | } |
301 | |
|
302 | 0 | break; |
303 | | |
304 | 0 | default: |
305 | 0 | expert_add_info(pinfo, tree, &ei_lsdp_unknown_msg_type); |
306 | 0 | break; |
307 | 0 | } |
308 | | |
309 | 0 | return msg_len; |
310 | 0 | } |
311 | | |
312 | | static int |
313 | | dissect_lsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
314 | 0 | { |
315 | 0 | int offset; |
316 | 0 | proto_item *ti; |
317 | 0 | proto_tree *lsdp_tree; |
318 | | |
319 | | /* Basic tests for LSDP */ |
320 | 0 | if( |
321 | 0 | tvb_reported_length(tvb) < LSDP_HEADER_LEN || // Header must be available |
322 | 0 | tvb_get_uint8(tvb, 0) != LSDP_HEADER_LEN || // Header length must be fixed |
323 | 0 | tvb_memeql(tvb, 1, LSDP_MAGIC, strlen(LSDP_MAGIC)) != 0 || // Magic Word must match |
324 | 0 | tvb_get_uint8(tvb, 5) != LSDP_HEADER_VER // We only support version 1 |
325 | 0 | ) |
326 | 0 | return 0; |
327 | | |
328 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSDP"); |
329 | 0 | col_clear(pinfo->cinfo,COL_INFO); |
330 | |
|
331 | 0 | ti = proto_tree_add_item(tree, proto_lsdp, tvb, 0, 0, ENC_NA); |
332 | 0 | lsdp_tree = proto_item_add_subtree(ti, ett_lsdp); |
333 | |
|
334 | 0 | offset = 0; |
335 | |
|
336 | 0 | proto_tree_add_item(lsdp_tree, hf_lsdp_header_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
337 | 0 | offset += 1; |
338 | |
|
339 | 0 | proto_tree_add_item(lsdp_tree, hf_lsdp_header_magic_word, tvb, offset, 4, ENC_ASCII); |
340 | 0 | offset += 4; |
341 | |
|
342 | 0 | proto_tree_add_item(lsdp_tree, hf_lsdp_header_proto_version, tvb, offset, 1, ENC_BIG_ENDIAN); |
343 | 0 | offset += 1; |
344 | | |
345 | | /* One packet can contain multiple messages */ |
346 | 0 | while((unsigned)offset < tvb_reported_length(tvb)) { |
347 | | |
348 | | /* |
349 | | Ensure there are enough bytes remaining for another message |
350 | | - at least 2 bytes (length, type) must be available |
351 | | - length must not be zero - ensure offset to advance |
352 | | */ |
353 | 0 | if( |
354 | 0 | tvb_reported_length_remaining(tvb, offset) < 2 || |
355 | 0 | tvb_get_uint8(tvb, offset) == 0 |
356 | 0 | ) |
357 | 0 | break; |
358 | | |
359 | 0 | offset += dissect_lsdp_message(tvb, pinfo, lsdp_tree, offset); |
360 | |
|
361 | 0 | } |
362 | |
|
363 | 0 | proto_item_set_len(ti, offset); |
364 | 0 | return offset; |
365 | 0 | } |
366 | | |
367 | | void |
368 | | proto_register_lsdp(void) |
369 | 14 | { |
370 | 14 | static hf_register_info hf[] = { |
371 | 14 | { &hf_lsdp_header_length, |
372 | 14 | { "Header Length", "lsdp.header.length", |
373 | 14 | FT_UINT8, BASE_DEC, |
374 | 14 | NULL, 0x0, |
375 | 14 | NULL, HFILL } |
376 | 14 | }, |
377 | 14 | { &hf_lsdp_header_magic_word, |
378 | 14 | { "Magic Word", "lsdp.header.magic_word", |
379 | 14 | FT_STRING, BASE_NONE, |
380 | 14 | NULL, 0x0, |
381 | 14 | NULL, HFILL } |
382 | 14 | }, |
383 | 14 | { &hf_lsdp_header_proto_version, |
384 | 14 | { "Protocol Version", "lsdp.header.proto_version", |
385 | 14 | FT_UINT8, BASE_DEC, |
386 | 14 | NULL, 0x0, |
387 | 14 | NULL, HFILL } |
388 | 14 | }, |
389 | 14 | { &hf_lsdp_msg_length, |
390 | 14 | { "Message Length", "lsdp.msg.length", |
391 | 14 | FT_UINT8, BASE_DEC, |
392 | 14 | NULL, 0x0, |
393 | 14 | NULL, HFILL } |
394 | 14 | }, |
395 | 14 | { &hf_lsdp_msg_type, |
396 | 14 | { "Message Type", "lsdp.msg.type", |
397 | 14 | FT_UINT8, BASE_HEX, |
398 | 14 | VALS(lsdp_msg_type_vals), 0x0, |
399 | 14 | NULL, HFILL } |
400 | 14 | }, |
401 | 14 | { &hf_lsdp_node_id_length, |
402 | 14 | { "Node ID Length", "lsdp.node_id.length", |
403 | 14 | FT_UINT8, BASE_DEC, |
404 | 14 | NULL, 0x0, |
405 | 14 | NULL, HFILL } |
406 | 14 | }, |
407 | 14 | { &hf_lsdp_node_id_mac, |
408 | 14 | { "Node ID (MAC)", "lsdp.node_id.mac", |
409 | 14 | FT_ETHER, BASE_NONE, |
410 | 14 | NULL, 0x0, |
411 | 14 | NULL, HFILL } |
412 | 14 | }, |
413 | 14 | { &hf_lsdp_node_id, |
414 | 14 | { "Node ID", "lsdp.node_id", |
415 | 14 | FT_BYTES, BASE_NONE, |
416 | 14 | NULL, 0x0, |
417 | 14 | NULL, HFILL } |
418 | 14 | }, |
419 | 14 | { &hf_lsdp_query, |
420 | 14 | { "Query Message", "lsdp.query", |
421 | 14 | FT_NONE, BASE_NONE, |
422 | 14 | NULL, 0x0, |
423 | 14 | NULL, HFILL } |
424 | 14 | }, |
425 | 14 | { &hf_lsdp_query_count, |
426 | 14 | { "Count", "lsdp.query.count", |
427 | 14 | FT_UINT8, BASE_DEC, |
428 | 14 | NULL, 0x0, |
429 | 14 | NULL, HFILL } |
430 | 14 | }, |
431 | 14 | { &hf_lsdp_query_class, |
432 | 14 | { "Class", "lsdp.query.class", |
433 | 14 | FT_UINT16, BASE_HEX, |
434 | 14 | VALS(lsdp_class_id_vals), 0x0, |
435 | 14 | NULL, HFILL } |
436 | 14 | }, |
437 | 14 | { &hf_lsdp_announce, |
438 | 14 | { "Announce Message", "lsdp.announce", |
439 | 14 | FT_NONE, BASE_NONE, |
440 | 14 | NULL, 0x0, |
441 | 14 | NULL, HFILL } |
442 | 14 | }, |
443 | 14 | { &hf_lsdp_announce_addr_length, |
444 | 14 | { "Address Length", "lsdp.announce.addr.length", |
445 | 14 | FT_UINT8, BASE_DEC, |
446 | 14 | NULL, 0x0, |
447 | 14 | NULL, HFILL } |
448 | 14 | }, |
449 | 14 | { &hf_lsdp_announce_addr_ipv4, |
450 | 14 | { "Address", "lsdp.announce.addr_ipv4", |
451 | 14 | FT_IPv4, BASE_NONE, |
452 | 14 | NULL, 0x0, |
453 | 14 | NULL, HFILL } |
454 | 14 | }, |
455 | 14 | { &hf_lsdp_announce_addr_ipv6, |
456 | 14 | { "Address", "lsdp.announce.addr_ipv6", |
457 | 14 | FT_IPv6, BASE_NONE, |
458 | 14 | NULL, 0x0, |
459 | 14 | NULL, HFILL } |
460 | 14 | }, |
461 | 14 | { &hf_lsdp_announce_count, |
462 | 14 | { "Count", "lsdp.announce.count", |
463 | 14 | FT_UINT8, BASE_DEC, |
464 | 14 | NULL, 0x0, |
465 | 14 | NULL, HFILL } |
466 | 14 | }, |
467 | 14 | { &hf_lsdp_announce_record, |
468 | 14 | { "Announce Record", "lsdp.announce.record", |
469 | 14 | FT_NONE, BASE_NONE, |
470 | 14 | NULL, 0x0, |
471 | 14 | NULL, HFILL } |
472 | 14 | }, |
473 | 14 | { &hf_lsdp_announce_record_class, |
474 | 14 | { "Class", "lsdp.announce.record.class", |
475 | 14 | FT_UINT16, BASE_HEX, |
476 | 14 | VALS(lsdp_class_id_vals), 0x0, |
477 | 14 | NULL, HFILL } |
478 | 14 | }, |
479 | 14 | { &hf_lsdp_announce_record_count, |
480 | 14 | { "Count", "lsdp.announce.record.count", |
481 | 14 | FT_UINT8, BASE_DEC, |
482 | 14 | NULL, 0x0, |
483 | 14 | NULL, HFILL } |
484 | 14 | }, |
485 | 14 | { &hf_lsdp_announce_record_txt, |
486 | 14 | { "TXT-Record", "lsdp.announce.record.txt", |
487 | 14 | FT_NONE, BASE_NONE, |
488 | 14 | NULL, 0x0, |
489 | 14 | NULL, HFILL } |
490 | 14 | }, |
491 | 14 | { &hf_lsdp_announce_record_txt_key_length, |
492 | 14 | { "Key Length", "lsdp.announce.record.txt.key.length", |
493 | 14 | FT_UINT8, BASE_DEC, |
494 | 14 | NULL, 0x0, |
495 | 14 | NULL, HFILL } |
496 | 14 | }, |
497 | 14 | { &hf_lsdp_announce_record_txt_key, |
498 | 14 | { "Key", "lsdp.announce.record.txt.key", |
499 | 14 | FT_STRING, BASE_NONE, |
500 | 14 | NULL, 0x0, |
501 | 14 | NULL, HFILL } |
502 | 14 | }, |
503 | 14 | { &hf_lsdp_announce_record_txt_value_length, |
504 | 14 | { "Value Length", "lsdp.announce.record.txt.val.length", |
505 | 14 | FT_UINT8, BASE_DEC, |
506 | 14 | NULL, 0x0, |
507 | 14 | NULL, HFILL } |
508 | 14 | }, |
509 | 14 | { &hf_lsdp_announce_record_txt_value, |
510 | 14 | { "Key", "lsdp.announce.record.txt.val", |
511 | 14 | FT_STRING, BASE_NONE, |
512 | 14 | NULL, 0x0, |
513 | 14 | NULL, HFILL } |
514 | 14 | }, |
515 | 14 | { &hf_lsdp_delete, |
516 | 14 | { "Delete Message", "lsdp.delete", |
517 | 14 | FT_NONE, BASE_NONE, |
518 | 14 | NULL, 0x0, |
519 | 14 | NULL, HFILL } |
520 | 14 | }, |
521 | 14 | { &hf_lsdp_delete_count, |
522 | 14 | { "Count", "lsdp.delete.count", |
523 | 14 | FT_UINT8, BASE_DEC, |
524 | 14 | NULL, 0x0, |
525 | 14 | NULL, HFILL } |
526 | 14 | }, |
527 | 14 | { &hf_lsdp_delete_class, |
528 | 14 | { "Class", "lsdp.delete.class", |
529 | 14 | FT_UINT16, BASE_HEX, |
530 | 14 | VALS(lsdp_class_id_vals), 0x0, |
531 | 14 | NULL, HFILL } |
532 | 14 | } |
533 | 14 | }; |
534 | | |
535 | 14 | static ei_register_info ei[] = { |
536 | 14 | { &ei_lsdp_unknown_msg_type, |
537 | 14 | { "lsdp.unknown_msg_type", PI_MALFORMED, PI_ERROR, |
538 | 14 | "Message is of invalid type", EXPFILL } |
539 | 14 | }, |
540 | 14 | { &ei_lsdp_invalid_addr_len, |
541 | 14 | { "lsdp.invalid_addr_len", PI_MALFORMED, PI_ERROR, |
542 | 14 | "Address has an invalid length", EXPFILL } |
543 | 14 | } |
544 | 14 | }; |
545 | | |
546 | 14 | static int *ett[] = { |
547 | 14 | &ett_lsdp, |
548 | 14 | &ett_lsdp_node_id, |
549 | 14 | &ett_lsdp_msg, |
550 | 14 | &ett_lsdp_msg_rec, |
551 | 14 | &ett_lsdp_msg_rec_txt |
552 | 14 | }; |
553 | | |
554 | 14 | expert_module_t* expert_lsdp; |
555 | | |
556 | 14 | proto_lsdp = proto_register_protocol ("Lenbrook Service Discovery Protocol", "LSDP", "lsdp"); |
557 | | |
558 | 14 | proto_register_field_array(proto_lsdp, hf, array_length(hf)); |
559 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
560 | | |
561 | 14 | expert_lsdp = expert_register_protocol(proto_lsdp); |
562 | 14 | expert_register_field_array(expert_lsdp, ei, array_length(ei)); |
563 | | |
564 | 14 | lsdp_handle = register_dissector("lsdp", dissect_lsdp, proto_lsdp); |
565 | 14 | } |
566 | | |
567 | | void |
568 | | proto_reg_handoff_lsdp(void) |
569 | 14 | { |
570 | 14 | dissector_add_uint("udp.port", LSDP_UDP_PORT, lsdp_handle); |
571 | 14 | } |
572 | | |
573 | | /* |
574 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
575 | | * |
576 | | * Local variables: |
577 | | * c-basic-offset: 4 |
578 | | * tab-width: 8 |
579 | | * indent-tabs-mode: nil |
580 | | * End: |
581 | | * |
582 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
583 | | * :indentSize=4:tabSize=8:noTabs=true: |
584 | | */ |