1 /* packet-hiqnet.c
2  * Harman HiQnet protocol dissector for Wireshark
3  * By Raphael Doursenaud <rdoursenaud@free.fr>
4  * Copyright 2014 Raphael Doursenaud
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 
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include "packet-tcp.h"
18 
19 /*
20  * See
21  *      https://adn.harmanpro.com/site_elements/resources/487_1411413911/HiQnet_third-party_programmers_quick-start_guide_original.pdf
22  *      https://adn.harmanpro.com/site_elements/resources/515_1414083576/HiQnet_Third_Party_Programmers_Guide_v2_original.pdf
23  */
24 
25 #define HIQNET_PORT 3804
26 
27 #define HIQNET_FLAGS_MASK   0x016f
28 
29 #define HIQNET_REQACK_FLAG      0x0001
30 #define HIQNET_ACK_FLAG         0x0002
31 #define HIQNET_INFO_FLAG        0x0004
32 #define HIQNET_ERROR_FLAG       0x0008
33 #define HIQNET_GUARANTEED_FLAG  0x0020
34 #define HIQNET_MULTIPART_FLAG   0x0040
35 #define HIQNET_SESSION_NUMBER_FLAG     0x0100
36 
37 #define HIQNET_SUBSCRIPTION_TYPE_MASK      0x07
38 
39 #define HIQNET_SUBSCRIPTION_FLAGS_MASK      0x00000001
40 
41 #define HIQNET_CATEGORIES_MASK  0x00004fff
42 
43 #define HIQNET_APPLICATION_CAT  0x00000002
44 #define HIQNET_CONF_CAT         0x00000004
45 #define HIQNET_AUDIONET_CAT     0x00000008
46 #define HIQNET_CTRLNET_CAT      0x00000010
47 #define HIQNET_VENDNET_CAT      0x00000020
48 #define HIQNET_STARTUP_CAT      0x00000040
49 #define HIQNET_DSP_CAT          0x00000080
50 #define HIQNET_MISC_CAT         0x00000100
51 #define HIQNET_CTRLLOG_CAT      0x00000200
52 #define HIQNET_FOREIGNPROTO_CAT 0x00000400
53 #define HIQNET_DIGIO_CAT        0x00000800
54 #define HIQNET_CTRLSURF_CAT     0x00004000
55 
56 /* Routing layer message IDs */
57 #define HIQNET_DISCOINFO_MSG        0x0000
58 #define HIQNET_RESERVED0_MSG        0x0001
59 #define HIQNET_GETNETINFO_MSG       0x0002
60 #define HIQNET_RESERVED1_MSG        0x0003
61 #define HIQNET_REQADDR_MSG          0x0004
62 #define HIQNET_ADDRUSED_MSG         0x0005
63 #define HIQNET_SETADDR_MSG          0x0006
64 #define HIQNET_GOODBYE_MSG          0x0007
65 #define HIQNET_HELLO_MSG            0x0008
66 
67 /* Other message IDs */
68 #define HIQNET_MULTPARMSET_MSG      0x0100
69 #define HIQNET_MULTOBJPARMSET_MSG   0x0101
70 #define HIQNET_PARMSETPCT_MSG       0x0102
71 #define HIQNET_MULTPARMGET_MSG      0x0103
72 #define HIQNET_GETATTR_MSG          0x010d
73 #define HIQNET_SETATTR_MSG          0x010e /* Reverse engineered. Not part of the official spec. */
74 #define HIQNET_MULTPARMSUB_MSG      0x010f
75 #define HIQNET_PARMSUBPCT_MSG       0x0111
76 #define HIQNET_MULTPARMUNSUB_MSG    0x0112
77 #define HIQNET_PARMSUBALL_MSG       0x0113
78 #define HIQNET_PARMUNSUBALL_MSG     0x0114
79 #define HIQNET_SUBEVTLOGMSGS_MSG    0x0115
80 #define HIQNET_GETVDLIST_MSG        0x011a
81 #define HIQNET_STORE_MSG            0x0124
82 #define HIQNET_RECALL_MSG           0x0125
83 #define HIQNET_LOCATE_MSG           0x0129
84 #define HIQNET_UNSUBEVTLOGMSGS_MSG  0x012b
85 #define HIQNET_REQEVTLOG_MSG        0x012c
86 
87 #define HIQNET_TCPIP_NET    1
88 #define HIQNET_RS232_NET    4
89 
90 static const value_string device_attributes_names[] = {
91     { 0, "Class Name" },
92     { 1, "Name String" },
93     /* Device Manager attributes */
94     { 2, "Flags" },
95     { 3, "Serial Number" },
96     { 4, "Software Version" },
97     { 0, NULL }
98 };
99 
100 static const value_string messageidnames[] = {
101     { HIQNET_DISCOINFO_MSG, "DiscoInfo" },
102     { HIQNET_RESERVED0_MSG, "Reserved" },
103     { HIQNET_GETNETINFO_MSG, "GetNetworkInfo" },
104     { HIQNET_RESERVED1_MSG, "Reserved" },
105     { HIQNET_REQADDR_MSG, "RequestAddress" },
106     { HIQNET_ADDRUSED_MSG, "AddressUsed" },
107     { HIQNET_SETADDR_MSG, "SetAddress" },
108     { HIQNET_GOODBYE_MSG, "Goodbye" },
109     { HIQNET_HELLO_MSG, "Hello" },
110     { HIQNET_MULTPARMSET_MSG, "MultiParamSet" },
111     { HIQNET_MULTOBJPARMSET_MSG, "MultiObjectParamSet" },
112     { HIQNET_PARMSETPCT_MSG, "ParamSetPercent" },
113     { HIQNET_MULTPARMGET_MSG, "MultiParamGet" },
114     { HIQNET_GETATTR_MSG, "GetAttributes" },
115     { HIQNET_MULTPARMSUB_MSG, "MultiParamSubscribe" },
116     { HIQNET_PARMSUBPCT_MSG, "ParamSubscribePercent" },
117     { HIQNET_SETATTR_MSG, "SetAttribute" }, /* Reverse engineered. Not part of the official spec. */
118     { HIQNET_MULTPARMUNSUB_MSG, "MultiParamUnsubscribe" },
119     { HIQNET_PARMSUBALL_MSG, "ParameterSubscribeAll" },
120     { HIQNET_PARMUNSUBALL_MSG, "ParameterUnSubscribeAll" },
121     { HIQNET_SUBEVTLOGMSGS_MSG, "Subscribe Event Log Messages" },
122     { HIQNET_GETVDLIST_MSG, "GetVDList" },
123     { HIQNET_STORE_MSG, "Store" },
124     { HIQNET_RECALL_MSG, "Recall" },
125     { HIQNET_LOCATE_MSG, "Locate" },
126     { HIQNET_UNSUBEVTLOGMSGS_MSG, "Unsubscribe Event Log Messages" },
127     { HIQNET_REQEVTLOG_MSG, "Request Event Log" },
128     { 0, NULL }
129 };
130 
131 #if 0
132 static const value_string flagnames[] = {
133     { HIQNET_REQACK_FLAG, "Request Acknowledgement" },
134     { HIQNET_ACK_FLAG, "Acknowledgement" },
135     { HIQNET_INFO_FLAG, "Information" },
136     { HIQNET_ERROR_FLAG, "Error" },
137     { HIQNET_GUARANTEED_FLAG, "Guaranteed" },
138     { HIQNET_MULTIPART_FLAG, "Multi-part" },
139     { HIQNET_SESSION_NUMBER_FLAG, "Session Number" },
140     { 0, NULL }
141 };
142 #endif
143 
144 #define HIQNET_DATATYPE_BYTE    0
145 #define HIQNET_DATATYPE_UBYTE   1
146 #define HIQNET_DATATYPE_WORD    2
147 #define HIQNET_DATATYPE_UWORD   3
148 #define HIQNET_DATATYPE_LONG    4
149 #define HIQNET_DATATYPE_ULONG   5
150 #define HIQNET_DATATYPE_FLOAT32 6
151 #define HIQNET_DATATYPE_FLOAT64 7
152 #define HIQNET_DATATYPE_BLOCK   8
153 #define HIQNET_DATATYPE_STRING  9
154 #define HIQNET_DATATYPE_LONG64  10
155 #define HIQNET_DATATYPE_ULONG64 11
156 
157 static const value_string datatypenames[] = {
158     { HIQNET_DATATYPE_BYTE,    "BYTE" },
159     { HIQNET_DATATYPE_UBYTE,   "UBYTE" },
160     { HIQNET_DATATYPE_WORD,    "WORD" },
161     { HIQNET_DATATYPE_UWORD,   "UWORD" },
162     { HIQNET_DATATYPE_LONG,    "LONG" },
163     { HIQNET_DATATYPE_ULONG,   "ULONG" },
164     { HIQNET_DATATYPE_FLOAT32, "FLOAT32" },
165     { HIQNET_DATATYPE_FLOAT64, "FLOAT64" },
166     { HIQNET_DATATYPE_BLOCK,   "BLOCK" },
167     { HIQNET_DATATYPE_STRING,  "STRING" },
168     { HIQNET_DATATYPE_LONG64,  "LONG64" },
169     { HIQNET_DATATYPE_ULONG64, "ULONG64" },
170     { 0, NULL }
171 };
172 
173 static const value_string actionnames[] = {
174     { 0, "Parameters" },
175     { 1, "Subscriptions" },
176     { 2, "Scenes" },
177     { 3, "Snapshots" },
178     { 4, "Presets" },
179     { 5, "Venue" },
180     { 0, NULL }
181 };
182 
183 static const value_string timenames[] = {
184     { 0x0000, "Turn off locate LEDs" },
185     { 0xffff, "Turn on locate LEDs" },
186     { 0, NULL }
187 };
188 
189 static const value_string eventcategorynames[] = {
190     { 0, "Unassigned" },
191     { 1, "Application" },
192     { 2, "Configuration" },
193     { 3, "Audio Network" },
194     { 4, "Control Network" },
195     { 5, "Vendor Network" },
196     { 6, "Startup" },
197     { 7, "DSP" },
198     { 8, "Miscellaneous" },
199     { 9, "Control Logic" },
200     { 10, "Foreign Protocol" },
201     { 11, "Digital I/O" },
202     { 12, "Unassigned" },
203     { 13, "Unassigned" },
204     { 14, "Control Surface" },
205     { 15, "Unassigned" },
206     { 16, "Unassigned" },
207     { 17, "Unassigned" },
208     { 18, "Unassigned" },
209     { 19, "Unassigned" },
210     { 20, "Unassigned" },
211     { 21, "Unassigned" },
212     { 22, "Unassigned" },
213     { 23, "Unassigned" },
214     { 24, "Unassigned" },
215     { 25, "Unassigned" },
216     { 26, "Unassigned" },
217     { 27, "Unassigned" },
218     { 28, "Unassigned" },
219     { 29, "Unassigned" },
220     { 30, "Unassigned" },
221     { 31, "Unassigned" },
222     { 0, NULL }
223 };
224 
225 static const value_string eventidnames[] = {
226     { 0x0001, "Invalid Version" },
227     { 0x0002, "Invalid Length" },
228     { 0x0003, "Invalid Virtual Device" },
229     { 0x0004, "Invalid Object" },
230     { 0x0005, "Invalid Parameter" },
231     { 0x0006, "Invalid Message ID" },
232     { 0x0007, "Invalid Value" },
233     { 0x0008, "Resource Unavailable" },
234     { 0x0009, "Unsupported" },
235     { 0x000a, "Invalid Virtual Device Class" },
236     { 0x000b, "Invalid Object Class" },
237     { 0x000c, "Invalid Parameter Class" },
238     { 0x000d, "Invalid Attribute ID" },
239     { 0x000e, "Invalid DataType" },
240     { 0x000f, "Invalid Configuration" },
241     { 0x0010, "Flash Error" },
242     { 0x0011, "Not a Router" },
243     { 0, NULL }
244 };
245 
246 static const value_string prioritynames[] = {
247     { 0, "Fault" },
248     { 1, "Warning" },
249     { 2, "Information" },
250     { 0, NULL }
251 };
252 
253 static const value_string networknames[] = {
254     { HIQNET_TCPIP_NET, "TCP/IP" },
255     { 2, "Reserved" },
256     { 3, "Reserved" },
257     { HIQNET_RS232_NET, "RS232" },
258     { 0, NULL }
259 };
260 
261 static const value_string paritynames[] = {
262     { 0, "None" },
263     { 1, "Odd" },
264     { 2, "Even" },
265     { 3, "Mark" },
266     { 4, "Space" },
267     { 0, NULL }
268 };
269 
270 static const value_string stopbitsnames[] = {
271     { 0, "1 Bits" },
272     { 1, "1.5 Bits" },
273     { 2, "2 Bits" },
274     { 0, NULL }
275 };
276 
277 static const value_string flowcontrolnames[] = {
278     { 0, "None" },
279     { 1, "Hardware" },
280     { 2, "XON/OFF" },
281     { 0, NULL }
282 };
283 
284 static int proto_hiqnet = -1;
285 
286 static int hf_hiqnet_version = -1;
287 
288 static gint ett_hiqnet = -1;
289 static gint ett_hiqnet_flags = -1;
290 static gint ett_hiqnet_cats = -1;
291 
292 static int hf_hiqnet_headerlen = -1;
293 static int hf_hiqnet_messagelen = -1;
294 static int hf_hiqnet_sourcedev = -1;
295 static int hf_hiqnet_sourceaddr = -1;
296 static int hf_hiqnet_destdev = -1;
297 static int hf_hiqnet_destaddr = -1;
298 static int hf_hiqnet_messageid = -1;
299 static int hf_hiqnet_flags = -1;
300 static int hf_hiqnet_reqack_flag = -1;
301 static int hf_hiqnet_ack_flag = -1;
302 static int hf_hiqnet_info_flag = -1;
303 static int hf_hiqnet_error_flag = -1;
304 static int hf_hiqnet_guaranteed_flag = -1;
305 static int hf_hiqnet_multipart_flag = -1;
306 static int hf_hiqnet_session_number_flag = -1;
307 static int hf_hiqnet_hopcnt = -1;
308 static int hf_hiqnet_seqnum = -1;
309 static int hf_hiqnet_errcode = -1;
310 static int hf_hiqnet_errstr = -1;
311 static int hf_hiqnet_startseqno = -1;
312 static int hf_hiqnet_rembytes = -1;
313 static int hf_hiqnet_sessnum = -1;
314 static int hf_hiqnet_cost = -1;
315 static int hf_hiqnet_sernumlen = -1;
316 static int hf_hiqnet_sernum = -1;
317 static int hf_hiqnet_maxmsgsize = -1;
318 static int hf_hiqnet_keepaliveperiod = -1;
319 static int hf_hiqnet_netid = -1;
320 static int hf_hiqnet_macaddr = -1;
321 static int hf_hiqnet_dhcp = -1;
322 static int hf_hiqnet_ipaddr = -1;
323 static int hf_hiqnet_subnetmsk = -1;
324 static int hf_hiqnet_gateway = -1;
325 static int hf_hiqnet_flagmask = -1;
326 static int hf_hiqnet_paramcount = -1;
327 static int hf_hiqnet_paramid = -1;
328 static int hf_hiqnet_vdobject = -1;
329 static int hf_hiqnet_subtype = -1;
330 static int hf_hiqnet_sensrate = -1;
331 static int hf_hiqnet_subflags = -1;
332 static int hf_hiqnet_subcount = -1;
333 static int hf_hiqnet_pubparmid = -1;
334 static int hf_hiqnet_subaddr = -1;
335 static int hf_hiqnet_subparmid = -1;
336 static int hf_hiqnet_reserved0 = -1;
337 static int hf_hiqnet_reserved1 = -1;
338 static int hf_hiqnet_attrcount = -1;
339 static int hf_hiqnet_attrid = -1;
340 static int hf_hiqnet_datatype = -1;
341 static int hf_hiqnet_datalen = -1;
342 static int hf_hiqnet_byte_value = -1;
343 static int hf_hiqnet_ubyte_value = -1;
344 static int hf_hiqnet_word_value = -1;
345 static int hf_hiqnet_uword_value = -1;
346 static int hf_hiqnet_long_value = -1;
347 static int hf_hiqnet_ulong_value = -1;
348 static int hf_hiqnet_float32_value = -1;
349 static int hf_hiqnet_float64_value = -1;
350 static int hf_hiqnet_block_value = -1;
351 static int hf_hiqnet_string_value = -1;
352 static int hf_hiqnet_long64_value = -1;
353 static int hf_hiqnet_ulong64_value = -1;
354 static int hf_hiqnet_wrkgrppath = -1;
355 static int hf_hiqnet_numvds = -1;
356 static int hf_hiqnet_vdaddr = -1;
357 static int hf_hiqnet_vdclassid = -1;
358 static int hf_hiqnet_stract = -1;
359 static int hf_hiqnet_strnum = -1;
360 static int hf_hiqnet_scope = -1;
361 static int hf_hiqnet_recact = -1;
362 static int hf_hiqnet_recnum = -1;
363 static int hf_hiqnet_strlen = -1;
364 static int hf_hiqnet_time = -1;
365 static int hf_hiqnet_maxdatasize = -1;
366 static int hf_hiqnet_catfilter = -1;
367 static int hf_hiqnet_app_cat = -1;
368 static int hf_hiqnet_conf_cat = -1;
369 static int hf_hiqnet_audionet_cat = -1;
370 static int hf_hiqnet_ctrlnet_cat = -1;
371 static int hf_hiqnet_vendnet_cat = -1;
372 static int hf_hiqnet_startup_cat = -1;
373 static int hf_hiqnet_dsp_cat = -1;
374 static int hf_hiqnet_misc_cat = -1;
375 static int hf_hiqnet_ctrlog_cat = -1;
376 static int hf_hiqnet_foreignproto_cat = -1;
377 static int hf_hiqnet_digio_cat = -1;
378 static int hf_hiqnet_ctrlsurf_cat = -1;
379 static int hf_hiqnet_entrieslen = -1;
380 static int hf_hiqnet_category = -1;
381 static int hf_hiqnet_eventid = -1;
382 static int hf_hiqnet_priority = -1;
383 static int hf_hiqnet_eventseqnum = -1;
384 static int hf_hiqnet_eventtime = -1;
385 static int hf_hiqnet_eventdate = -1;
386 static int hf_hiqnet_eventinfo = -1;
387 static int hf_hiqnet_eventadddata = -1;
388 static int hf_hiqnet_objcount = -1;
389 static int hf_hiqnet_paramval = -1;
390 static int hf_hiqnet_ifacecount = -1;
391 static int hf_hiqnet_comid = -1;
392 static int hf_hiqnet_baudrate = -1;
393 static int hf_hiqnet_parity = -1;
394 static int hf_hiqnet_stopbits = -1;
395 static int hf_hiqnet_databits = -1;
396 static int hf_hiqnet_flowcontrol = -1;
397 static int hf_hiqnet_devaddr = -1;
398 static int hf_hiqnet_newdevaddr = -1;
399 
400 static expert_field ei_hiqnet_datatype = EI_INIT;
401 
402 static int * const hiqnet_flag_fields[] = {
403     &hf_hiqnet_reqack_flag,
404     &hf_hiqnet_ack_flag,
405     &hf_hiqnet_info_flag,
406     &hf_hiqnet_error_flag,
407     &hf_hiqnet_guaranteed_flag,
408     &hf_hiqnet_multipart_flag,
409     &hf_hiqnet_session_number_flag,
410     NULL
411 };
412 
413 static int * const hiqnet_cat_fields[] = {
414     &hf_hiqnet_app_cat,
415     &hf_hiqnet_conf_cat,
416     &hf_hiqnet_audionet_cat,
417     &hf_hiqnet_ctrlnet_cat,
418     &hf_hiqnet_vendnet_cat,
419     &hf_hiqnet_startup_cat,
420     &hf_hiqnet_dsp_cat,
421     &hf_hiqnet_misc_cat,
422     &hf_hiqnet_ctrlog_cat,
423     &hf_hiqnet_foreignproto_cat,
424     &hf_hiqnet_digio_cat,
425     &hf_hiqnet_ctrlsurf_cat,
426     NULL
427 };
428 
429 void proto_register_hiqnet(void);
430 void proto_reg_handoff_hiqnet(void);
431 
432 
433 static void
hiqnet_display_vdobjectaddr(proto_tree * hiqnet_tree,int hf_hiqnet,tvbuff_t * tvb,gint offset)434 hiqnet_display_vdobjectaddr(proto_tree *hiqnet_tree, int hf_hiqnet, tvbuff_t *tvb, gint offset) {
435     proto_tree_add_bytes_format_value(hiqnet_tree, hf_hiqnet, tvb, offset, 4, NULL,
436         "%u.%u.%u.%u",
437         tvb_get_guint8(tvb, offset), /* Virtual Device address */
438         tvb_get_guint8(tvb, offset + 1), /* Object address part 1 */
439         tvb_get_guint8(tvb, offset + 2), /* Object address part 2 */
440         tvb_get_guint8(tvb, offset + 3)); /* Object address part 3 */
441 }
442 
443 
444 static gint
hiqnet_display_tcpipnetinfo(proto_tree * hiqnet_payload_tree,tvbuff_t * tvb,gint offset)445 hiqnet_display_tcpipnetinfo(proto_tree *hiqnet_payload_tree, tvbuff_t *tvb, gint offset) {
446     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_macaddr, tvb, offset, 6, ENC_NA);
447     offset += 6;
448     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_dhcp, tvb, offset, 1, ENC_BIG_ENDIAN);
449     offset += 1;
450     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
451     offset += 4;
452     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subnetmsk, tvb, offset, 4, ENC_BIG_ENDIAN);
453     offset += 4;
454     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_gateway, tvb, offset, 4, ENC_BIG_ENDIAN);
455     offset += 4;
456     return offset;
457 }
458 
459 
460 static gint
hiqnet_display_rs232netinfo(proto_tree * hiqnet_payload_tree,tvbuff_t * tvb,gint offset)461 hiqnet_display_rs232netinfo(proto_tree *hiqnet_payload_tree, tvbuff_t *tvb, gint offset) {
462     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_comid, tvb, offset, 1, ENC_BIG_ENDIAN);
463     offset += 1;
464     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_baudrate, tvb, offset, 4, ENC_BIG_ENDIAN);
465     offset += 4;
466     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_parity, tvb, offset, 1, ENC_BIG_ENDIAN);
467     offset += 1;
468     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_stopbits, tvb, offset, 1, ENC_BIG_ENDIAN);
469     offset += 1;
470     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_databits, tvb, offset, 1, ENC_BIG_ENDIAN);
471     offset += 1;
472     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_flowcontrol, tvb, offset, 1, ENC_BIG_ENDIAN);
473     offset += 1;
474     return offset;
475 }
476 
477 
478 static gint
hiqnet_display_netinfo(proto_tree * hiqnet_payload_tree,tvbuff_t * tvb,gint offset)479 hiqnet_display_netinfo(proto_tree *hiqnet_payload_tree, tvbuff_t *tvb, gint offset) {
480     guint netid = 0;
481     netid = tvb_get_guint8(tvb, offset);
482     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_netid, tvb, offset, 1, ENC_BIG_ENDIAN);
483     offset += 1;
484     if (netid == HIQNET_TCPIP_NET) {
485             offset = hiqnet_display_tcpipnetinfo(hiqnet_payload_tree, tvb, offset);
486     }
487     if (netid == HIQNET_RS232_NET) {
488         offset = hiqnet_display_rs232netinfo(hiqnet_payload_tree, tvb, offset);
489     }
490     return offset;
491 }
492 
493 
494 static gint
hiqnet_display_sernum(proto_tree * hiqnet_payload_tree,tvbuff_t * tvb,gint offset)495 hiqnet_display_sernum(proto_tree *hiqnet_payload_tree, tvbuff_t *tvb, gint offset) {
496     gint str_len;
497     str_len = tvb_get_ntohs(tvb, offset);
498     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_sernumlen, tvb, offset, 2, ENC_BIG_ENDIAN);
499     offset += 2;
500     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_sernum, tvb, offset, str_len, ENC_NA);
501     offset += str_len;
502     return offset;
503 }
504 
505 
506 static gint
hiqnet_display_paramsub(proto_tree * hiqnet_payload_tree,tvbuff_t * tvb,gint offset)507 hiqnet_display_paramsub(proto_tree *hiqnet_payload_tree, tvbuff_t *tvb, gint offset) {
508     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_pubparmid, tvb, offset, 2, ENC_BIG_ENDIAN);
509     offset += 2;
510     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
511     offset += 1;
512     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subaddr, tvb, offset, 6, ENC_NA);
513     offset += 6;
514     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subparmid, tvb, offset, 2, ENC_BIG_ENDIAN);
515     offset += 2;
516     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_reserved0, tvb, offset, 1, ENC_NA);
517     offset += 1;
518     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_reserved1, tvb, offset, 2, ENC_NA);
519     offset += 2;
520     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_sensrate, tvb, offset, 2, ENC_BIG_ENDIAN);
521     offset += 2;
522     return offset;
523 }
524 
525 
526 /* TODO: decode flags for attributes and parameters */
527 static gint
hiqnet_display_data(proto_tree * hiqnet_payload_tree,packet_info * pinfo,tvbuff_t * tvb,gint offset)528 hiqnet_display_data(proto_tree *hiqnet_payload_tree, packet_info *pinfo, tvbuff_t *tvb, gint offset) {
529     guint32 datatype;
530     guint32 datalen;
531     proto_item* ti;
532 
533     ti = proto_tree_add_item_ret_uint(hiqnet_payload_tree, hf_hiqnet_datatype, tvb, offset, 1, ENC_BIG_ENDIAN, &datatype);
534     offset += 1;
535     switch (datatype) {
536 
537     case HIQNET_DATATYPE_BYTE:
538         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_byte_value, tvb, offset, 1, ENC_BIG_ENDIAN);
539         offset += 1;
540         break;
541 
542     case HIQNET_DATATYPE_UBYTE:
543         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_ubyte_value, tvb, offset, 1, ENC_BIG_ENDIAN);
544         offset += 1;
545         break;
546 
547     case HIQNET_DATATYPE_WORD:
548         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_word_value, tvb, offset, 2, ENC_BIG_ENDIAN);
549         offset += 2;
550         break;
551 
552     case HIQNET_DATATYPE_UWORD:
553         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_uword_value, tvb, offset, 2, ENC_BIG_ENDIAN);
554         offset += 2;
555         break;
556 
557     case HIQNET_DATATYPE_LONG:
558         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_long_value, tvb, offset, 4, ENC_BIG_ENDIAN);
559         offset += 4;
560         break;
561 
562     case HIQNET_DATATYPE_ULONG:
563         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_ulong_value, tvb, offset, 4, ENC_BIG_ENDIAN);
564         offset += 4;
565         break;
566 
567     case HIQNET_DATATYPE_FLOAT32:
568         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_float32_value, tvb, offset, 4, ENC_BIG_ENDIAN);
569         offset += 4;
570         break;
571 
572     case HIQNET_DATATYPE_FLOAT64:
573         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_float64_value, tvb, offset, 8, ENC_BIG_ENDIAN);
574         offset += 8;
575         break;
576 
577     case HIQNET_DATATYPE_BLOCK:
578         proto_tree_add_item_ret_uint(hiqnet_payload_tree, hf_hiqnet_datalen, tvb, offset, 2, ENC_BIG_ENDIAN, &datalen);
579         offset += 2;
580         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_block_value, tvb, offset, datalen, ENC_NA);
581         offset += datalen;
582         break;
583 
584     case HIQNET_DATATYPE_STRING:
585         proto_tree_add_item_ret_uint(hiqnet_payload_tree, hf_hiqnet_datalen, tvb, offset, 2, ENC_BIG_ENDIAN, &datalen);
586         offset += 2;
587         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_string_value, tvb, offset, datalen, ENC_UCS_2|ENC_BIG_ENDIAN);
588         offset += datalen;
589         break;
590 
591     case HIQNET_DATATYPE_LONG64:
592         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_long64_value, tvb, offset, 8, ENC_BIG_ENDIAN);
593         offset += 8;
594         break;
595 
596     case HIQNET_DATATYPE_ULONG64:
597         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_ulong64_value, tvb, offset, 8, ENC_BIG_ENDIAN);
598         offset += 8;
599         break;
600 
601     default:
602         /* Flag an error, and punt and assume these values have no length. */
603         expert_add_info(pinfo, ti, &ei_hiqnet_datatype);
604         break;
605     }
606     return offset;
607 }
608 
609 static int
dissect_hiqnet_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)610 dissect_hiqnet_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
611 {
612     guint8 headerlen = 0;
613     guint32 messagelen = 0;
614     guint16 srcdev = 0;
615     guint8 srcvdaddr = 0;
616     guint8 srcob0addr = 0;
617     guint8 srcob1addr = 0;
618     guint8 srcob2addr = 0;
619     guint16 dstdev = 0;
620     guint8 dstvdaddr = 0;
621     guint8 dstob0addr = 0;
622     guint8 dstob1addr = 0;
623     guint8 dstob2addr = 0;
624     guint16 messageid = 0;
625     guint16 flags = 0;
626     guint16 paramcount = 0;
627     guint16 subcount = 0;
628     guint16 attrcount = 0;
629     gint str_len = 0;
630     guint16 vdscount = 0;
631     guint16 eventscount = 0;
632     guint16 objcount = 0;
633     guint16 ifacecount = 0;
634 
635     col_set_str(pinfo->cinfo, COL_PROTOCOL, "HiQnet");
636     /* Clear out stuff in the info column */
637     col_clear(pinfo->cinfo,COL_INFO);
638 
639     srcdev = tvb_get_ntohs(tvb, 6);
640     srcvdaddr = tvb_get_guint8(tvb, 8);
641     srcob0addr = tvb_get_guint8(tvb, 9);
642     srcob1addr = tvb_get_guint8(tvb, 10);
643     srcob2addr = tvb_get_guint8(tvb, 11);
644     dstdev = tvb_get_ntohs(tvb, 12);
645     dstvdaddr = tvb_get_guint8(tvb, 14);
646     dstob0addr = tvb_get_guint8(tvb, 15);
647     dstob1addr = tvb_get_guint8(tvb, 16);
648     dstob2addr = tvb_get_guint8(tvb, 17);
649     messageid = tvb_get_ntohs(tvb, 18);
650     col_add_fstr(pinfo->cinfo, COL_INFO, "Msg: %s, Src: %u.%u.%u.%u.%u, Dst: %u.%u.%u.%u.%u",
651         val_to_str(messageid, messageidnames, "Unknown (0x%04x)"),
652         srcdev, srcvdaddr, srcob0addr, srcob1addr, srcob2addr,
653         dstdev, dstvdaddr, dstob0addr, dstob1addr, dstob2addr);
654 
655     if (tree) { /* we are being asked for details */
656         proto_item *ti = NULL;
657         proto_item *item = NULL;
658         proto_tree *hiqnet_tree = NULL;
659         proto_tree *hiqnet_header_tree = NULL;
660         proto_tree *hiqnet_session_tree = NULL;
661         proto_tree *hiqnet_error_tree = NULL;
662         proto_tree *hiqnet_multipart_tree = NULL;
663         proto_tree *hiqnet_payload_tree = NULL;
664         proto_tree *hiqnet_parameter_tree = NULL;
665         proto_tree *hiqnet_attribute_tree = NULL;
666         proto_tree *hiqnet_vds_tree = NULL;
667         proto_tree *hiqnet_event_tree = NULL;
668         proto_tree *hiqnet_subscription_tree = NULL;
669         proto_tree *hiqnet_object_tree = NULL;
670         proto_tree *hiqnet_ifaces_tree = NULL;
671         gint offset = 0;
672 
673         messagelen = tvb_get_ntohl(tvb, 2);
674         ti = proto_tree_add_item(tree, proto_hiqnet, tvb, 0, messagelen, ENC_NA);
675         proto_item_append_text(ti, ", Msg: %s",
676             val_to_str(messageid, messageidnames, "Unknown (0x%04x)"));
677         proto_item_append_text(ti, ", Src %u.%u.%u.%u.%u",
678             srcdev, srcvdaddr, srcob0addr, srcob1addr, srcob2addr);
679         proto_item_append_text(ti, ", Dst: %u.%u.%u.%u.%u",
680             dstdev, dstvdaddr, dstob0addr, dstob1addr, dstob2addr);
681         hiqnet_tree = proto_item_add_subtree(ti, ett_hiqnet);
682 
683         /* Header subtree */
684         headerlen =  tvb_get_guint8(tvb, 1);
685         hiqnet_header_tree = proto_tree_add_subtree(hiqnet_tree, tvb, 0, headerlen, ett_hiqnet, NULL, "Header");
686 
687         /* Standard header */
688         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_version, tvb, offset, 1, ENC_BIG_ENDIAN);
689         offset += 1;
690         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_headerlen, tvb, offset, 1, ENC_BIG_ENDIAN);
691         offset += 1;
692         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_messagelen, tvb, offset, 4, ENC_BIG_ENDIAN);
693         offset += 4;
694         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_sourcedev, tvb, offset, 2, ENC_BIG_ENDIAN);
695         item = proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
696         proto_item_set_hidden(item);
697         offset += 2;
698         hiqnet_display_vdobjectaddr(hiqnet_header_tree, hf_hiqnet_sourceaddr, tvb, offset);
699         offset += 4;
700         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_destdev, tvb, offset, 2, ENC_BIG_ENDIAN);
701         item = proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
702         proto_item_set_hidden(item);
703         offset += 2;
704         hiqnet_display_vdobjectaddr(hiqnet_header_tree, hf_hiqnet_destaddr, tvb, offset);
705         offset += 4;
706         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_messageid, tvb, offset, 2, ENC_BIG_ENDIAN);
707         offset += 2;
708         flags = tvb_get_ntohs(tvb, offset);
709         proto_tree_add_bitmask(hiqnet_header_tree, tvb, offset, hf_hiqnet_flags,
710                                ett_hiqnet_flags, hiqnet_flag_fields, ENC_BIG_ENDIAN);
711         offset += 2;
712         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_hopcnt, tvb, offset, 1, ENC_BIG_ENDIAN);
713         offset += 1;
714         proto_tree_add_item(hiqnet_header_tree, hf_hiqnet_seqnum, tvb, offset, 2, ENC_BIG_ENDIAN);
715         offset += 2;
716 
717         /* Optional headers */
718         if (flags & HIQNET_ERROR_FLAG) {
719             /* TODO: mark the erroneous frame */
720             hiqnet_error_tree = proto_tree_add_subtree(hiqnet_header_tree, tvb, offset, 2, ett_hiqnet, NULL, "Error");
721             proto_tree_add_item(hiqnet_error_tree, hf_hiqnet_errcode, tvb, offset, 1, ENC_BIG_ENDIAN);
722             offset += 1;
723             proto_tree_add_item(hiqnet_error_tree, hf_hiqnet_errstr, tvb, offset, headerlen - offset, ENC_UCS_2|ENC_BIG_ENDIAN);
724         }
725         if (flags & HIQNET_MULTIPART_FLAG) {
726             /* TODO: rebuild the full message */
727             hiqnet_multipart_tree = proto_tree_add_subtree(hiqnet_header_tree, tvb, offset, 2, ett_hiqnet, NULL, "Multi-part");
728             proto_tree_add_item(hiqnet_multipart_tree, hf_hiqnet_startseqno, tvb, offset, 1, ENC_BIG_ENDIAN);
729             offset += 1;
730             proto_tree_add_item(hiqnet_multipart_tree, hf_hiqnet_rembytes, tvb, offset, 4, ENC_BIG_ENDIAN);
731             offset += 4;
732         }
733         if (flags & HIQNET_SESSION_NUMBER_FLAG) {
734             hiqnet_session_tree = proto_tree_add_subtree(hiqnet_header_tree, tvb, offset, 2, ett_hiqnet, NULL, "Session");
735             proto_tree_add_item(hiqnet_session_tree, hf_hiqnet_sessnum, tvb, offset, 2, ENC_BIG_ENDIAN);
736         }
737 
738         /* Payload(s) */
739         offset = headerlen; /* Make sure we are at the payload start */
740         hiqnet_payload_tree = proto_tree_add_subtree(
741             hiqnet_tree, tvb, offset, messagelen - headerlen, ett_hiqnet, NULL, "Payload");
742         switch(messageid) {
743             case HIQNET_DISCOINFO_MSG :
744                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
745                 offset += 2;
746                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_cost, tvb, offset, 1, ENC_BIG_ENDIAN);
747                 offset += 1;
748                 offset = hiqnet_display_sernum(hiqnet_payload_tree, tvb, offset);
749                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_maxmsgsize, tvb, offset, 4, ENC_BIG_ENDIAN);
750                 offset += 4;
751                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_keepaliveperiod, tvb, offset, 2, ENC_BIG_ENDIAN);
752                 offset += 2;
753                 hiqnet_display_netinfo(hiqnet_payload_tree, tvb, offset);
754                 break;
755             case HIQNET_HELLO_MSG :
756                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_sessnum, tvb, offset, 2, ENC_BIG_ENDIAN);
757                 offset += 2;
758                 proto_tree_add_bitmask(hiqnet_payload_tree, tvb, offset, hf_hiqnet_flagmask,
759                                ett_hiqnet_flags, hiqnet_flag_fields, ENC_BIG_ENDIAN);
760                 break;
761             case HIQNET_MULTPARMGET_MSG :
762                 paramcount = tvb_get_ntohs(tvb, offset);
763                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_paramcount, tvb, offset, 2, ENC_BIG_ENDIAN);
764                 offset += 2;
765                 while (paramcount > 0) {
766                     hiqnet_parameter_tree = proto_tree_add_subtree(
767                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Parameter");
768                     proto_tree_add_item(hiqnet_parameter_tree, hf_hiqnet_paramid, tvb, offset, 2, ENC_BIG_ENDIAN);
769                     offset += 2;
770                     if (flags & HIQNET_INFO_FLAG) { /* This is not a request */
771                         offset = hiqnet_display_data(hiqnet_parameter_tree, pinfo, tvb, offset);
772                     }
773                     paramcount -= 1;
774                 }
775                 break;
776             case HIQNET_MULTPARMSET_MSG :
777                 paramcount = tvb_get_ntohs(tvb, offset);
778                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_paramcount, tvb, offset, 2, ENC_BIG_ENDIAN);
779                 offset += 2;
780                 while (paramcount > 0) {
781                     hiqnet_parameter_tree = proto_tree_add_subtree(
782                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Parameter");
783                     proto_tree_add_item(hiqnet_parameter_tree, hf_hiqnet_paramid, tvb, offset, 2, ENC_BIG_ENDIAN);
784                     offset += 2;
785                     offset = hiqnet_display_data(hiqnet_parameter_tree, pinfo, tvb, offset);
786                     paramcount -= 1;
787                 }
788                 break;
789             case HIQNET_PARMSUBALL_MSG :
790                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
791                 offset += 2;
792                 hiqnet_display_vdobjectaddr(hiqnet_payload_tree, hf_hiqnet_vdobject, tvb, offset);
793                 offset += 4;
794                 /* TODO: can be decoded in two ways (old and new) */
795                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
796                 offset += 1;
797                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_sensrate, tvb, offset, 2, ENC_BIG_ENDIAN);
798                 offset += 2;
799                 /* TODO: decode and display */
800                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subflags, tvb, offset, 2, ENC_BIG_ENDIAN);
801                 break;
802             case HIQNET_PARMUNSUBALL_MSG : /* Reverse engineered. Not part of the official spec. */
803                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
804                 offset += 2;
805                 hiqnet_display_vdobjectaddr(hiqnet_payload_tree, hf_hiqnet_vdobject, tvb, offset);
806                 offset += 4;
807                 /* TODO: can be decoded in two ways (old and new) */
808                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
809                 break;
810             case HIQNET_MULTPARMSUB_MSG :
811                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
812                 subcount = tvb_get_ntohs(tvb, offset);
813                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subcount, tvb, offset, 2, ENC_BIG_ENDIAN);
814                 offset += 2;
815                 while (subcount > 0) {
816                     hiqnet_subscription_tree = proto_tree_add_subtree(
817                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Subscription");
818                     offset = hiqnet_display_paramsub(hiqnet_subscription_tree, tvb, offset);
819                     subcount -= 1;
820                 }
821                 break;
822             case HIQNET_GOODBYE_MSG :
823                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
824                 break;
825             case HIQNET_GETATTR_MSG :
826                 attrcount = tvb_get_ntohs(tvb, offset);
827                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_attrcount, tvb, offset, 2, ENC_BIG_ENDIAN);
828                 offset += 2;
829                 if (flags & HIQNET_INFO_FLAG) { /* This not a request */
830                     while (attrcount > 0) {
831                         hiqnet_attribute_tree = proto_tree_add_subtree(
832                             hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Attribute");
833                         proto_tree_add_item(hiqnet_attribute_tree, hf_hiqnet_attrid, tvb, offset, 2, ENC_BIG_ENDIAN);
834                         offset += 2;
835                         offset = hiqnet_display_data(hiqnet_attribute_tree, pinfo, tvb, offset);
836                         attrcount -= 1;
837                     }
838                 } else { /* This may be a request */
839                     while (attrcount > 0) {
840                         proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_attrid, tvb, offset, 2, ENC_BIG_ENDIAN);
841                         offset += 2;
842                         attrcount -= 1;
843                     }
844                 }
845                 break;
846             case HIQNET_GETVDLIST_MSG :
847                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
848                 str_len = tvb_get_ntohs(tvb, offset);
849                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_strlen, tvb, offset, 2, ENC_BIG_ENDIAN);
850                 offset += 2;
851                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_wrkgrppath, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
852                 offset += str_len;
853                 if (flags & HIQNET_INFO_FLAG) { /* This is not a request */
854                     vdscount = tvb_get_ntohs(tvb, offset);
855                     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_numvds, tvb, offset, 2, ENC_BIG_ENDIAN);
856                     offset += 2;
857                     while (vdscount > 0) {
858                         hiqnet_vds_tree = proto_tree_add_subtree(
859                             hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Virtual Devices");
860                         proto_tree_add_item(hiqnet_vds_tree, hf_hiqnet_vdaddr, tvb, offset, 1, ENC_BIG_ENDIAN);
861                         offset += 1;
862                         proto_tree_add_item(hiqnet_vds_tree, hf_hiqnet_vdclassid, tvb, offset, 2, ENC_BIG_ENDIAN);
863                         offset += 2;
864                         vdscount -= 1;
865                     }
866                 }
867                 break;
868             case HIQNET_STORE_MSG :
869                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
870                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_stract, tvb, offset, 1, ENC_BIG_ENDIAN);
871                 offset += 1;
872                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_strnum, tvb, offset, 2, ENC_BIG_ENDIAN);
873                 offset += 2;
874                 str_len = tvb_get_ntohs(tvb, offset);
875                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_strlen, tvb, offset, 2, ENC_BIG_ENDIAN);
876                 offset += 2;
877                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_wrkgrppath, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
878                 offset += str_len;
879                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
880                 break;
881             case HIQNET_RECALL_MSG :
882                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_recact, tvb, offset, 1, ENC_BIG_ENDIAN);
883                 offset += 1;
884                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_recnum, tvb, offset, 2, ENC_BIG_ENDIAN);
885                 offset += 2;
886                 str_len = tvb_get_ntohs(tvb, offset);
887                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_strlen, tvb, offset, 2, ENC_BIG_ENDIAN);
888                 offset += 2;
889                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_wrkgrppath, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
890                 offset += str_len;
891                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
892                 break;
893             case HIQNET_LOCATE_MSG :
894                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_time, tvb, offset, 2, ENC_BIG_ENDIAN);
895                 offset += 2;
896                 hiqnet_display_sernum(hiqnet_payload_tree, tvb, offset);
897                 break;
898             case HIQNET_SUBEVTLOGMSGS_MSG :
899                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_maxdatasize, tvb, offset, 2, ENC_BIG_ENDIAN);
900                 offset += 2;
901                 proto_tree_add_bitmask(hiqnet_payload_tree, tvb, offset, hf_hiqnet_catfilter,
902                                ett_hiqnet_cats, hiqnet_cat_fields, ENC_BIG_ENDIAN);
903                 break;
904             case HIQNET_UNSUBEVTLOGMSGS_MSG :
905                 proto_tree_add_bitmask(hiqnet_payload_tree, tvb, offset, hf_hiqnet_catfilter,
906                                ett_hiqnet_cats, hiqnet_cat_fields, ENC_BIG_ENDIAN);
907                 break;
908             case HIQNET_REQEVTLOG_MSG :
909                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
910                 if (flags & HIQNET_INFO_FLAG) { /* This is not a request */
911                     eventscount = tvb_get_ntohs(tvb, offset);
912                     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_entrieslen, tvb, offset, 2, ENC_BIG_ENDIAN);
913                     offset += 2;
914                     while (eventscount > 0) {
915                         hiqnet_event_tree = proto_tree_add_subtree(
916                             hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Event");
917 
918                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_category, tvb, offset, 2, ENC_BIG_ENDIAN);
919                         offset += 2;
920 
921                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_eventid, tvb, offset, 2, ENC_BIG_ENDIAN);
922                         offset += 2;
923                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
924                         offset += 1;
925                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_eventseqnum, tvb, offset, 4, ENC_BIG_ENDIAN);
926                         offset += 4;
927                         str_len = tvb_get_ntohs(tvb, offset);
928                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_eventtime, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
929                         offset += str_len;
930                         str_len = tvb_get_ntohs(tvb, offset);
931                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_eventdate, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
932                         offset += str_len;
933                         str_len = tvb_get_ntohs(tvb, offset);
934                         proto_tree_add_item(hiqnet_event_tree, hf_hiqnet_eventinfo, tvb, offset, str_len, ENC_UCS_2|ENC_BIG_ENDIAN);
935                         offset += str_len;
936                         str_len = tvb_get_ntohs(tvb, offset);
937                         proto_tree_add_item(
938                             hiqnet_event_tree, hf_hiqnet_eventadddata, tvb, offset, str_len, ENC_NA);
939                         offset += str_len;
940                         eventscount -= 1;
941                     }
942                 }
943                 break;
944             case HIQNET_MULTPARMUNSUB_MSG :
945                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
946                 subcount = tvb_get_ntohs(tvb, offset);
947                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subcount, tvb, offset, 2, ENC_BIG_ENDIAN);
948                 offset += 2;
949                 while (subcount > 0) {
950                     hiqnet_subscription_tree = proto_tree_add_subtree(
951                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Subscription");
952                     proto_tree_add_item(hiqnet_subscription_tree, hf_hiqnet_pubparmid, tvb, offset, 2, ENC_BIG_ENDIAN);
953                     offset += 2;
954                     proto_tree_add_item(hiqnet_subscription_tree, hf_hiqnet_subparmid, tvb, offset, 2, ENC_BIG_ENDIAN);
955                     offset += 2;
956                     subcount -= 1;
957                 }
958                 break;
959             case HIQNET_MULTOBJPARMSET_MSG :
960                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
961                 objcount = tvb_get_ntohs(tvb, offset);
962                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_objcount, tvb, offset, 2, ENC_BIG_ENDIAN);
963                 offset += 2;
964                 while (objcount > 0) {
965                     hiqnet_object_tree = proto_tree_add_subtree(
966                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Object");
967                     hiqnet_display_vdobjectaddr(hiqnet_header_tree, hf_hiqnet_vdobject, tvb, offset);
968                     offset += 4;
969                     paramcount = tvb_get_ntohs(tvb, offset);
970                     proto_tree_add_item(hiqnet_object_tree, hf_hiqnet_paramcount, tvb, offset, 2, ENC_BIG_ENDIAN);
971                     offset += 2;
972                     while (paramcount > 0) {
973                         hiqnet_parameter_tree = proto_tree_add_subtree(
974                             hiqnet_object_tree, tvb, offset, -1, ett_hiqnet, NULL, "Parameter");
975                         proto_tree_add_item(hiqnet_parameter_tree, hf_hiqnet_paramid, tvb, offset, 2, ENC_BIG_ENDIAN);
976                         offset += 2;
977                         offset = hiqnet_display_data(hiqnet_parameter_tree, pinfo, tvb, offset);
978                         paramcount -= 1;
979                     }
980                     objcount -= 1;
981                 }
982                 break;
983             case HIQNET_PARMSETPCT_MSG :
984                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
985                 paramcount = tvb_get_ntohs(tvb, offset);
986                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_paramcount, tvb, offset, 2, ENC_BIG_ENDIAN);
987                 offset += 2;
988                 while (paramcount > 0) {
989                     hiqnet_parameter_tree = proto_tree_add_subtree(
990                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Parameter");
991                     proto_tree_add_item(hiqnet_parameter_tree, hf_hiqnet_paramid, tvb, offset, 2, ENC_BIG_ENDIAN);
992                     offset += 2;
993                     /* TODO: docode paramval is in percentage represented as a 1.15 signed fixed point format */
994                     proto_tree_add_item(hiqnet_parameter_tree, hf_hiqnet_paramval, tvb, offset, 2, ENC_BIG_ENDIAN);
995                     offset += 2;
996                     paramcount -= 1;
997                 }
998                 break;
999             case HIQNET_PARMSUBPCT_MSG :
1000                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
1001                 subcount = tvb_get_ntohs(tvb, offset);
1002                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_subcount, tvb, offset, 2, ENC_BIG_ENDIAN);
1003                 offset += 2;
1004                 while (subcount > 0) {
1005                     hiqnet_subscription_tree = proto_tree_add_subtree(
1006                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Subscription");
1007                     offset = hiqnet_display_paramsub(hiqnet_subscription_tree, tvb, offset);
1008                     subcount -= 1;
1009                 }
1010                 break;
1011             case HIQNET_GETNETINFO_MSG :
1012                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
1013                 offset = hiqnet_display_sernum(hiqnet_payload_tree, tvb, offset);
1014                 if (flags & HIQNET_INFO_FLAG) { /* This is not a request */
1015                     ifacecount = tvb_get_ntohs(tvb, offset);
1016                     proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_ifacecount, tvb, offset, 2, ENC_BIG_ENDIAN);
1017                     offset += 2;
1018                     while (ifacecount > 0) {
1019                         hiqnet_ifaces_tree = proto_tree_add_subtree(
1020                             hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Interface");
1021                         proto_tree_add_item(hiqnet_ifaces_tree, hf_hiqnet_maxmsgsize, tvb, offset, 4, ENC_BIG_ENDIAN);
1022                         offset += 4;
1023                         offset = hiqnet_display_netinfo(hiqnet_ifaces_tree, tvb, offset);
1024                         ifacecount -= 1;
1025                     }
1026                 }
1027                 break;
1028             case HIQNET_REQADDR_MSG :
1029                 /* FIXME: Not tested, straight from the spec, never occurred with the devices I own */
1030                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_devaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
1031                 break;
1032             case HIQNET_SETADDR_MSG :
1033                 offset = hiqnet_display_sernum(hiqnet_payload_tree, tvb, offset);
1034                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_newdevaddr, tvb, offset, 2, ENC_BIG_ENDIAN);
1035                 offset += 2;
1036                 hiqnet_display_netinfo(hiqnet_payload_tree, tvb, offset);
1037                 break;
1038             case HIQNET_SETATTR_MSG : /* Reverse engineered. Not part of the official spec. */
1039                 attrcount = tvb_get_ntohs(tvb, offset);
1040                 proto_tree_add_item(hiqnet_payload_tree, hf_hiqnet_attrcount, tvb, offset, 2, ENC_BIG_ENDIAN);
1041                 offset += 2;
1042                 while (attrcount > 0) {
1043                     hiqnet_attribute_tree = proto_tree_add_subtree(
1044                         hiqnet_payload_tree, tvb, offset, -1, ett_hiqnet, NULL, "Attribute");
1045                     proto_tree_add_item(hiqnet_attribute_tree, hf_hiqnet_attrid, tvb, offset, 2, ENC_BIG_ENDIAN);
1046                     offset += 2;
1047                     offset = hiqnet_display_data(hiqnet_attribute_tree, pinfo, tvb, offset);
1048                     attrcount -= 1;
1049                 }
1050                 break;
1051                 /* FIXME: Messages unknown, assumed without payload */
1052             case HIQNET_RESERVED0_MSG:
1053             case HIQNET_RESERVED1_MSG:
1054                 /* Message without payload */
1055             case HIQNET_ADDRUSED_MSG:
1056                 break;
1057             default : /* Unknown message or malformed packet */
1058                 /* TODO: display something useful? */
1059                 break;
1060         }
1061     }
1062     return tvb_reported_length(tvb);
1063 }
1064 
1065 
1066 static guint
get_hiqnet_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)1067 get_hiqnet_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1068 {
1069     /* length is at offset + 2 */
1070     return tvb_get_ntohl(tvb, offset + 2);
1071 }
1072 
1073 /* Fixme: For multiple hiqnet PDUS in a single TCP or UDP packet,
1074    the INFO column shows the information only for the last PDU */
1075 
1076 static int
dissect_hiqnet_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1077 dissect_hiqnet_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1078 {
1079     tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 6,
1080                      get_hiqnet_pdu_len, dissect_hiqnet_pdu, data);
1081     return tvb_captured_length(tvb);
1082 }
1083 
1084 static int
dissect_hiqnet_udp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1085 dissect_hiqnet_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1086 {
1087     gint      offset = 0;
1088     tvbuff_t *next_tvb;
1089     gint      offset_before;
1090     guint     plen;
1091     guint     captured_length;
1092 
1093     /* loop on (possibly multiple) hiqnet PDUs in UDP payload */
1094     while (tvb_reported_length_remaining(tvb, offset) > 0) {
1095         plen = get_hiqnet_pdu_len(pinfo, tvb, offset, NULL);
1096         captured_length = tvb_captured_length_remaining(tvb, offset);
1097 
1098         if (captured_length > plen)
1099             captured_length = plen;
1100         next_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_length, plen);
1101 
1102         dissect_hiqnet_pdu(next_tvb, pinfo, tree, data);
1103 
1104         /*
1105          * Step to the next PDU.
1106          * Make sure we don't overflow.
1107          */
1108         offset_before = offset;
1109         offset += plen;
1110         if (offset <= offset_before)
1111             break;
1112     }
1113     return tvb_captured_length(tvb);
1114 }
1115 
1116 void
proto_register_hiqnet(void)1117 proto_register_hiqnet(void)
1118 {
1119     static hf_register_info hf[] = {
1120         { &hf_hiqnet_version,
1121             { "Version", "hiqnet.version",
1122                 FT_UINT8, BASE_DEC,
1123                 NULL, 0x0,
1124                 NULL, HFILL }
1125         },
1126         { &hf_hiqnet_headerlen,
1127             { "Header length", "hiqnet.hlen",
1128                 FT_UINT16, BASE_DEC,
1129                 NULL, 0x0,
1130                 NULL, HFILL }
1131         },
1132         { &hf_hiqnet_messagelen,
1133             { "Message length", "hiqnet.mlen",
1134                 FT_UINT32, BASE_DEC,
1135                 NULL, 0x0,
1136                 NULL, HFILL }
1137         },
1138         { &hf_hiqnet_sourcedev,
1139             { "Source device", "hiqnet.srcdev",
1140                 FT_UINT16, BASE_DEC_HEX,
1141                 NULL, 0x0,
1142                 NULL, HFILL }
1143         },
1144         { &hf_hiqnet_sourceaddr,
1145             { "Source address", "hiqnet.srcaddr",
1146                 FT_BYTES, BASE_NONE,
1147                 NULL, 0x0,
1148                 NULL, HFILL }
1149         },
1150         { &hf_hiqnet_destdev,
1151             { "Destination device", "hiqnet.dstdev",
1152                 FT_UINT16, BASE_DEC_HEX,
1153                 NULL, 0x0,
1154                 NULL, HFILL }
1155         },
1156         { &hf_hiqnet_destaddr,
1157             { "Destination address", "hiqnet.dstaddr",
1158                 FT_BYTES, BASE_NONE,
1159                 NULL, 0x0,
1160                 NULL, HFILL }
1161         },
1162         { &hf_hiqnet_messageid,
1163             { "Message ID", "hiqnet.msgid",
1164                 FT_UINT16, BASE_HEX,
1165                 VALS(messageidnames), 0x0,
1166                 NULL, HFILL }
1167         },
1168         { &hf_hiqnet_flags,
1169             { "Flags", "hiqnet.flags",
1170                 FT_UINT16, BASE_HEX,
1171                 NULL, HIQNET_FLAGS_MASK,
1172                 NULL, HFILL }
1173         },
1174         { &hf_hiqnet_reqack_flag,
1175             { "Request Acknowledgement", "hiqnet.flags.reqack",
1176                 FT_BOOLEAN, 16,
1177                 NULL, HIQNET_REQACK_FLAG,
1178                 NULL, HFILL }
1179         },
1180         { &hf_hiqnet_ack_flag,
1181             { "Acknowledgement", "hiqnet.flags.ack",
1182                 FT_BOOLEAN, 16,
1183                 NULL, HIQNET_ACK_FLAG,
1184                 NULL, HFILL }
1185         },
1186         { &hf_hiqnet_info_flag,
1187             { "Information", "hiqnet.flags.info",
1188                 FT_BOOLEAN, 16,
1189                 NULL, HIQNET_INFO_FLAG,
1190                 NULL, HFILL }
1191         },
1192         { &hf_hiqnet_error_flag,
1193             { "Error", "hiqnet.flags.error",
1194                 FT_BOOLEAN, 16,
1195                 NULL, HIQNET_ERROR_FLAG,
1196                 NULL, HFILL }
1197         },
1198         { &hf_hiqnet_guaranteed_flag,
1199             { "Guaranteed", "hiqnet.flags.guar",
1200                 FT_BOOLEAN, 16,
1201                 NULL, HIQNET_GUARANTEED_FLAG,
1202                 NULL, HFILL }
1203         },
1204         { &hf_hiqnet_multipart_flag,
1205             { "Multipart", "hiqnet.flags.multi",
1206                 FT_BOOLEAN, 16,
1207                 NULL, HIQNET_MULTIPART_FLAG,
1208                 NULL, HFILL }
1209         },
1210         { &hf_hiqnet_session_number_flag,
1211             { "Session Number", "hiqnet.flags.session_number",
1212                 FT_BOOLEAN, 16,
1213                 NULL, HIQNET_SESSION_NUMBER_FLAG,
1214                 NULL, HFILL }
1215         },
1216         { &hf_hiqnet_hopcnt,
1217             { "Hop count", "hiqnet.hc",
1218                 FT_UINT8, BASE_DEC,
1219                 NULL, 0x0,
1220                 NULL, HFILL }
1221         },
1222         { &hf_hiqnet_seqnum,
1223             { "Sequence number", "hiqnet.seqnum",
1224                 FT_UINT16, BASE_DEC,
1225                 NULL, 0x0,
1226                 NULL, HFILL }
1227         },
1228         { &hf_hiqnet_errcode,
1229             { "Error code", "hiqnet.errcode",
1230                 FT_UINT8, BASE_DEC_HEX,
1231                 NULL, 0x0,
1232                 NULL, HFILL }
1233         },
1234         { &hf_hiqnet_errstr,
1235             { "Error string", "hiqnet.errstr",
1236                 FT_STRINGZ, STR_UNICODE,
1237                 NULL, 0x0,
1238                 NULL, HFILL }
1239         },
1240         { &hf_hiqnet_startseqno,
1241             { "Start seq. no.", "hiqnet.ssno",
1242                 FT_UINT8, BASE_DEC,
1243                 NULL, 0x0,
1244                 NULL, HFILL }
1245         },
1246         { &hf_hiqnet_rembytes,
1247             { "Remaining bytes", "hiqnet.rembytes",
1248                 FT_UINT32, BASE_DEC,
1249                 NULL, 0x0,
1250                 NULL, HFILL }
1251         },
1252         { &hf_hiqnet_sessnum,
1253             { "Session number", "hiqnet.sessnum",
1254                 FT_UINT16, BASE_DEC,
1255                 NULL, 0x0,
1256                 NULL, HFILL }
1257         },
1258         { &hf_hiqnet_cost,
1259             { "Cost", "hiqnet.cost",
1260                 FT_UINT8, BASE_DEC,
1261                 NULL, 0x0,
1262                 NULL, HFILL }
1263         },
1264         { &hf_hiqnet_sernumlen,
1265             { "Serial number length", "hiqnet.sernumlen",
1266                 FT_UINT16, BASE_DEC,
1267                 NULL, 0x0,
1268                 NULL, HFILL }
1269         },
1270         { &hf_hiqnet_sernum,
1271             { "Serial number", "hiqnet.sernum",
1272                 FT_BYTES, BASE_NONE,
1273                 NULL, 0x0,
1274                 NULL, HFILL }
1275         },
1276         { &hf_hiqnet_maxmsgsize,
1277             { "Max message size", "hiqnet.maxmsgsize",
1278                 FT_UINT32, BASE_DEC,
1279                 NULL, 0x0,
1280                 NULL, HFILL }
1281         },
1282         { &hf_hiqnet_keepaliveperiod,
1283             { "Keepalive period (ms)", "hiqnet.keepaliveperiod",
1284                 FT_UINT16, BASE_DEC,
1285                 NULL, 0x0,
1286                 NULL, HFILL }
1287         },
1288         { &hf_hiqnet_netid,
1289             { "Network ID", "hiqnet.netid",
1290                 FT_UINT8, BASE_DEC,
1291                 VALS(networknames), 0x0,
1292                 NULL, HFILL }
1293         },
1294         { &hf_hiqnet_macaddr,
1295             { "MAC address", "hiqnet.macaddr",
1296                 FT_ETHER, BASE_NONE,
1297                 NULL, 0x0,
1298                 NULL, HFILL }
1299         },
1300         { &hf_hiqnet_dhcp,
1301             { "DHCP", "hiqnet.dhcp",
1302                 FT_BOOLEAN, BASE_NONE,
1303                 NULL, 0x0,
1304                 NULL, HFILL }
1305         },
1306         { &hf_hiqnet_ipaddr,
1307             { "IP Address", "hiqnet.ipaddr",
1308                 FT_IPv4, BASE_NONE,
1309                 NULL, 0x0,
1310                 NULL, HFILL }
1311         },
1312         { &hf_hiqnet_subnetmsk,
1313             { "Subnet mask", "hiqnet.subnetmsk",
1314                 FT_IPv4, BASE_NONE,
1315                 NULL, 0x0,
1316                 NULL, HFILL }
1317         },
1318         { &hf_hiqnet_gateway,
1319             { "Gateway", "hiqnet.gateway",
1320                 FT_IPv4, BASE_NONE,
1321                 NULL, 0x0,
1322                 NULL, HFILL }
1323         },
1324         { &hf_hiqnet_flagmask,
1325             { "Flag mask", "hiqnet.flagmask",
1326                 FT_UINT16, BASE_HEX,
1327                 NULL, HIQNET_FLAGS_MASK,
1328                 NULL, HFILL }
1329         },
1330         { &hf_hiqnet_paramcount,
1331             { "Parameter count", "hiqnet.paramcount",
1332                 FT_UINT16, BASE_DEC,
1333                 NULL, 0x0,
1334                 NULL, HFILL }
1335         },
1336         { &hf_hiqnet_paramid,
1337             { "Parameter ID", "hiqnet.paramid",
1338                 FT_UINT16, BASE_DEC,
1339                 NULL, 0x0,
1340                 NULL, HFILL }
1341         },
1342         { &hf_hiqnet_vdobject,
1343             { "Virtual Device Object", "hiqnet.vdobject",
1344                 FT_BYTES, BASE_NONE,
1345                 NULL, 0x0,
1346                 NULL, HFILL }
1347         },
1348         { &hf_hiqnet_subtype,
1349             { "Subscription Type (New Style)", "hiqnet.subtype",
1350                 FT_UINT8, BASE_DEC,
1351                 NULL, HIQNET_SUBSCRIPTION_TYPE_MASK,
1352                 NULL, HFILL }
1353         },
1354         /* FIXME: decode old style subscription type
1355         { &hf_hiqnet_subtypeold,
1356             { "Subscription Type (Old Style)", "hiqnet.subtype",
1357                 FT_UINT8, BASE_DEC,
1358                 VALS(subscription_types_oldstyle_names), 0x0,
1359                 NULL, HFILL }
1360         },
1361         */
1362         { &hf_hiqnet_sensrate,
1363             { "Sensor Rate (ms)", "hiqnet.sensrate",
1364                 FT_UINT16, BASE_DEC,
1365                 NULL, 0x0,
1366                 NULL, HFILL }
1367         },
1368         { &hf_hiqnet_subflags,
1369             { "Subscription Flags", "hiqnet.subflags",
1370                 FT_UINT16, BASE_HEX,
1371                 NULL, HIQNET_SUBSCRIPTION_FLAGS_MASK,
1372                 NULL, HFILL }
1373         },
1374         { &hf_hiqnet_subcount,
1375             { "No of Subscriptions", "hiqnet.subcount",
1376                 FT_UINT16, BASE_DEC,
1377                 NULL, 0x0,
1378                 NULL, HFILL }
1379         },
1380         { &hf_hiqnet_pubparmid,
1381             { "Publisher Parameter ID", "hiqnet.pubparmid",
1382                 FT_UINT16, BASE_DEC,
1383                 NULL, 0x0,
1384                 NULL, HFILL }
1385         },
1386         { &hf_hiqnet_subaddr,
1387             { "Subscriber Address", "hiqnet.subaddr",
1388                 FT_BYTES, BASE_NONE,
1389                 NULL, 0x0,
1390                 NULL, HFILL }
1391         },
1392         { &hf_hiqnet_subparmid,
1393             { "Subscriber Parameter ID", "hiqnet.subparmid",
1394                 FT_UINT16, BASE_DEC,
1395                 NULL, 0x0,
1396                 NULL, HFILL }
1397         },
1398         { &hf_hiqnet_reserved0,
1399             { "Reserved", "hiqnet.reserved0",
1400                 FT_BYTES, BASE_NONE,
1401                 NULL, 0x0,
1402                 NULL, HFILL }
1403         },
1404         { &hf_hiqnet_reserved1,
1405             { "Reserved", "hiqnet.reserved1",
1406                 FT_BYTES, BASE_NONE,
1407                 NULL, 0x0,
1408                 NULL, HFILL }
1409         },
1410         { &hf_hiqnet_attrcount,
1411             { "Attribute count", "hiqnet.attrcount",
1412                 FT_UINT16, BASE_DEC,
1413                 NULL, 0x0,
1414                 NULL, HFILL }
1415         },
1416         { &hf_hiqnet_attrid,
1417             { "Attribute ID", "hiqnet.attrid",
1418                 FT_UINT16, BASE_DEC,
1419                 VALS(device_attributes_names), 0x0,
1420                 NULL, HFILL }
1421         },
1422         { &hf_hiqnet_datatype,
1423             { "Data type", "hiqnet.datatype",
1424                 FT_UINT8, BASE_HEX,
1425                 VALS(datatypenames), 0x0,
1426                 NULL, HFILL }
1427         },
1428         { &hf_hiqnet_datalen,
1429             { "Data length", "hiqnet.datalen",
1430                 FT_UINT16, BASE_DEC,
1431                 NULL, 0x0,
1432                 NULL, HFILL }
1433         },
1434         { &hf_hiqnet_byte_value,
1435             { "Value", "hiqnet.byte_value",
1436                 FT_INT8, BASE_DEC,
1437                 NULL, 0x0,
1438                 NULL, HFILL }
1439         },
1440         { &hf_hiqnet_ubyte_value,
1441             { "Value", "hiqnet.ubyte_value",
1442                 FT_UINT8, BASE_DEC_HEX,
1443                 NULL, 0x0,
1444                 NULL, HFILL }
1445         },
1446         { &hf_hiqnet_word_value,
1447             { "Value", "hiqnet.word_value",
1448                 FT_INT16, BASE_DEC,
1449                 NULL, 0x0,
1450                 NULL, HFILL }
1451         },
1452         { &hf_hiqnet_uword_value,
1453             { "Value", "hiqnet.uword_value",
1454                 FT_UINT16, BASE_DEC_HEX,
1455                 NULL, 0x0,
1456                 NULL, HFILL }
1457         },
1458         { &hf_hiqnet_long_value,
1459             { "Value", "hiqnet.long_value",
1460                 FT_INT32, BASE_DEC,
1461                 NULL, 0x0,
1462                 NULL, HFILL }
1463         },
1464         { &hf_hiqnet_ulong_value,
1465             { "Value", "hiqnet.ulong_value",
1466                 FT_UINT32, BASE_DEC_HEX,
1467                 NULL, 0x0,
1468                 NULL, HFILL }
1469         },
1470         { &hf_hiqnet_float32_value,
1471             { "Value", "hiqnet.float32_value",
1472                 FT_FLOAT, BASE_NONE,
1473                 NULL, 0x0,
1474                 NULL, HFILL }
1475         },
1476         { &hf_hiqnet_float64_value,
1477             { "Value", "hiqnet.float64_value",
1478                 FT_DOUBLE, BASE_NONE,
1479                 NULL, 0x0,
1480                 NULL, HFILL }
1481         },
1482         { &hf_hiqnet_block_value,
1483             { "Value", "hiqnet.block_value",
1484                 FT_BYTES, BASE_NONE,
1485                 NULL, 0x0,
1486                 NULL, HFILL }
1487         },
1488         /* Counted *and* null-terminated */
1489         { &hf_hiqnet_string_value,
1490             { "Value", "hiqnet.string_value",
1491                 FT_STRINGZ, STR_UNICODE,
1492                 NULL, 0x0,
1493                 NULL, HFILL }
1494         },
1495         { &hf_hiqnet_long64_value,
1496             { "Value", "hiqnet.long64_value",
1497                 FT_INT64, BASE_DEC,
1498                 NULL, 0x0,
1499                 NULL, HFILL }
1500         },
1501         { &hf_hiqnet_ulong64_value,
1502             { "Value", "hiqnet.ulong64_value",
1503                 FT_UINT64 , BASE_DEC_HEX,
1504                 NULL, 0x0,
1505                 NULL, HFILL }
1506         },
1507         { &hf_hiqnet_wrkgrppath,
1508             { "Workgroup Path", "hiqnet.wrkgrppath",
1509                 FT_STRINGZ, STR_UNICODE,
1510                 NULL, 0x0,
1511                 NULL, HFILL }
1512         },
1513         { &hf_hiqnet_numvds,
1514             { "Number of Virtual Devices", "hiqnet.numvds",
1515                 FT_UINT16, BASE_DEC,
1516                 NULL, 0x0,
1517                 NULL, HFILL }
1518         },
1519         { &hf_hiqnet_vdaddr,
1520             { "Virtual Device Address", "hiqnet.vdaddr",
1521                 FT_UINT8, BASE_DEC,
1522                 NULL, 0x0,
1523                 NULL, HFILL }
1524         },
1525         { &hf_hiqnet_vdclassid,
1526             { "Virtual Device Class ID", "hiqnet.vdclassid",
1527                 FT_UINT16, BASE_HEX,
1528                 NULL, 0x0,
1529                 NULL, HFILL }
1530         },
1531         { &hf_hiqnet_stract,
1532             { "Store Action", "hiqnet.stract",
1533                 FT_UINT8, BASE_DEC,
1534                 VALS(actionnames), 0x0,
1535                 NULL, HFILL }
1536         },
1537         { &hf_hiqnet_strnum,
1538             { "Store Number", "hiqnet.strnum",
1539                 FT_UINT16, BASE_DEC,
1540                 NULL, 0x0,
1541                 NULL, HFILL }
1542         },
1543         { &hf_hiqnet_scope,
1544             { "Scope", "hiqnet.scope",
1545                 FT_UINT8, BASE_HEX,
1546                 NULL, 0x0,
1547                 NULL, HFILL }
1548         },
1549         { &hf_hiqnet_recact,
1550             { "Recall Action", "hiqnet.rec.act",
1551                 FT_UINT8, BASE_DEC,
1552                 VALS(actionnames), 0x0,
1553                 NULL, HFILL }
1554         },
1555         { &hf_hiqnet_recnum,
1556             { "Recall Number", "hiqnet.recnum",
1557                 FT_UINT16, BASE_DEC,
1558                 NULL, 0x0,
1559                 NULL, HFILL }
1560         },
1561         { &hf_hiqnet_strlen,
1562             { "String length", "hiqnet.strlen",
1563                 FT_UINT16, BASE_DEC,
1564                 NULL, 0x0,
1565                 NULL, HFILL }
1566         },
1567         { &hf_hiqnet_time,
1568             { "Locate time (ms)", "hiqnet.time",
1569                 FT_UINT16, BASE_DEC,
1570                 VALS(timenames), 0x0,
1571                 NULL, HFILL }
1572         },
1573         { &hf_hiqnet_maxdatasize,
1574             { "Maximum Data Size", "hiqnet.maxdatasize",
1575                 FT_UINT16, BASE_DEC,
1576                 NULL, 0x0,
1577                 NULL, HFILL }
1578         },
1579         { &hf_hiqnet_catfilter,
1580             { "Category Filter", "hiqnet.catfilter",
1581                 FT_UINT32, BASE_HEX,
1582                 NULL, HIQNET_CATEGORIES_MASK,
1583                 NULL, HFILL }
1584         },
1585         { &hf_hiqnet_app_cat,
1586             { "Application", "hiqnet.appcat",
1587                 FT_BOOLEAN, 32,
1588                 NULL, HIQNET_APPLICATION_CAT,
1589                 NULL, HFILL }
1590         },
1591         { &hf_hiqnet_conf_cat,
1592             { "Configuration", "hiqnet.confcat",
1593                 FT_BOOLEAN, 32,
1594                 NULL, HIQNET_CONF_CAT,
1595                 NULL, HFILL }
1596         },
1597         { &hf_hiqnet_audionet_cat,
1598             { "Audio Network", "hiqnet.audionetcat",
1599                 FT_BOOLEAN, 32,
1600                 NULL, HIQNET_AUDIONET_CAT,
1601                 NULL, HFILL }
1602         },
1603         { &hf_hiqnet_ctrlnet_cat,
1604             { "Control Network", "hiqnet.ctrlnetcat",
1605                 FT_BOOLEAN, 32,
1606                 NULL, HIQNET_CTRLNET_CAT,
1607                 NULL, HFILL }
1608         },
1609         { &hf_hiqnet_vendnet_cat,
1610             { "Vendor Network", "hiqnet.vendnetcat",
1611                 FT_BOOLEAN, 32,
1612                 NULL, HIQNET_VENDNET_CAT,
1613                 NULL, HFILL }
1614         },
1615         { &hf_hiqnet_startup_cat,
1616             { "Startup", "hiqnet.startupcat",
1617                 FT_BOOLEAN, 32,
1618                 NULL, HIQNET_STARTUP_CAT,
1619                 NULL, HFILL }
1620         },
1621         { &hf_hiqnet_dsp_cat,
1622             { "DSP", "hiqnet.dspcat",
1623                 FT_BOOLEAN, 32,
1624                 NULL, HIQNET_DSP_CAT,
1625                 NULL, HFILL }
1626         },
1627         { &hf_hiqnet_misc_cat,
1628             { "Miscellaneous", "hiqnet.misccat",
1629                 FT_BOOLEAN, 32,
1630                 NULL, HIQNET_MISC_CAT,
1631                 NULL, HFILL }
1632         },
1633         { &hf_hiqnet_ctrlog_cat,
1634             { "Control Logic", "hiqnet.crtllogcat",
1635                 FT_BOOLEAN, 32,
1636                 NULL, HIQNET_CTRLLOG_CAT,
1637                 NULL, HFILL }
1638         },
1639         { &hf_hiqnet_foreignproto_cat,
1640             { "Foreign Protocol", "hiqnet.foreignprotocat",
1641                 FT_BOOLEAN, 32,
1642                 NULL, HIQNET_FOREIGNPROTO_CAT,
1643                 NULL, HFILL }
1644         },
1645         { &hf_hiqnet_digio_cat,
1646             { "Digital I/O", "hiqnet.digiocat",
1647                 FT_BOOLEAN, 32,
1648                 NULL, HIQNET_DIGIO_CAT,
1649                 NULL, HFILL }
1650         },
1651         { &hf_hiqnet_ctrlsurf_cat,
1652             { "Control Surface", "hiqnet.ctrlsurfcat",
1653                 FT_BOOLEAN, 32,
1654                 NULL, HIQNET_CTRLSURF_CAT,
1655                 NULL, HFILL }
1656         },
1657         { &hf_hiqnet_entrieslen,
1658             { "Number of Entries", "hiqnet.entrieslen",
1659                 FT_UINT16, BASE_DEC,
1660                 NULL, 0x0,
1661                 NULL, HFILL }
1662         },
1663         { &hf_hiqnet_category,
1664             { "Category", "hiqnet.cat",
1665                 FT_UINT16, BASE_HEX,
1666                 VALS(eventcategorynames), 0x0,
1667                 NULL, HFILL }
1668         },
1669         { &hf_hiqnet_eventid,
1670             { "Event ID", "hiqnet.eventid",
1671                 FT_UINT16, BASE_DEC,
1672                 VALS(eventidnames), 0x0,
1673                 NULL, HFILL }
1674         },
1675         { &hf_hiqnet_priority,
1676             { "Priority", "hiqnet.priority",
1677                 FT_UINT8, BASE_DEC,
1678                 VALS(prioritynames), 0x0,
1679                 NULL, HFILL }
1680         },
1681         { &hf_hiqnet_eventseqnum,
1682             { "Sequence Number", "hiqnet.eventseqnum",
1683                 FT_UINT32, BASE_DEC,
1684                 NULL, 0x0,
1685                 NULL, HFILL }
1686         },
1687         { &hf_hiqnet_eventtime,
1688             { "Time", "hiqnet.eventtime",
1689                 FT_STRING, STR_UNICODE,
1690                 NULL, 0x0,
1691                 NULL, HFILL }
1692         },
1693         { &hf_hiqnet_eventdate,
1694             { "Date", "hiqnet.eventdate",
1695                 FT_STRING, STR_UNICODE,
1696                 NULL, 0x0,
1697                 NULL, HFILL }
1698         },
1699         { &hf_hiqnet_eventinfo,
1700             { "Information", "hiqnet.information",
1701                 FT_STRING, STR_UNICODE,
1702                 NULL, 0x0,
1703                 NULL, HFILL }
1704         },
1705         { &hf_hiqnet_eventadddata,
1706             { "Additional Data", "hiqnet.eventadddata",
1707                 FT_BYTES, BASE_NONE,
1708                 NULL, 0x0,
1709                 NULL, HFILL }
1710         },
1711         { &hf_hiqnet_objcount,
1712             { "Object Count", "hiqnet.objcount",
1713                 FT_UINT16, BASE_DEC,
1714                 NULL, 0x0,
1715                 NULL, HFILL }
1716         },
1717         { &hf_hiqnet_paramval,
1718             { "Parameter Value (%)", "hiqnet.paramval",
1719                 FT_INT16, BASE_DEC,
1720                 NULL, 0x0,
1721                 NULL, HFILL }
1722         },
1723         { &hf_hiqnet_ifacecount,
1724             { "Interface Count", "hiqnet.ifacecount",
1725                 FT_UINT16, BASE_DEC,
1726                 NULL, 0x0,
1727                 NULL, HFILL }
1728         },
1729         { &hf_hiqnet_comid,
1730             { "Com Port Identifier", "hiqnet.comid",
1731                 FT_UINT8, BASE_DEC,
1732                 NULL, 0x0,
1733                 NULL, HFILL }
1734         },
1735         { &hf_hiqnet_baudrate,
1736             { "Baud Rate", "hiqnet.baudrate",
1737                 FT_UINT32, BASE_DEC,
1738                 NULL, 0x0,
1739                 NULL, HFILL }
1740         },
1741         { &hf_hiqnet_parity,
1742             { "Parity", "hiqnet.parity",
1743                 FT_UINT8, BASE_DEC,
1744                 VALS(paritynames), 0x0,
1745                 NULL, HFILL }
1746         },
1747         { &hf_hiqnet_stopbits,
1748             { "Stop Bits", "hiqnet.stopbits",
1749                 FT_UINT8, BASE_DEC,
1750                 VALS(stopbitsnames), 0x0,
1751                 NULL, HFILL }
1752         },
1753         { &hf_hiqnet_databits,
1754             { "Data Bits", "hiqnet.databits",
1755                 FT_UINT8, BASE_DEC,
1756                 NULL, 0x0,
1757                 NULL, HFILL }
1758         },
1759         { &hf_hiqnet_flowcontrol,
1760             { "Flowcontrol", "hiqnet.flowcontrol",
1761                 FT_UINT8, BASE_DEC,
1762                 VALS(flowcontrolnames), 0x0,
1763                 NULL, HFILL }
1764         },
1765         { &hf_hiqnet_devaddr,
1766             { "Device Address", "hiqnet.device",
1767                 FT_UINT16, BASE_DEC_HEX,
1768                 NULL, 0x0,
1769                 NULL, HFILL }
1770         },
1771         { &hf_hiqnet_newdevaddr,
1772             { "New Device Address", "hiqnet.device",
1773                 FT_UINT16, BASE_DEC_HEX,
1774                 NULL, 0x0,
1775                 NULL, HFILL }
1776         }
1777     };
1778 
1779     /* Setup protocol subtree array */
1780     static gint *ett[] = {
1781         &ett_hiqnet,
1782         &ett_hiqnet_flags,
1783         &ett_hiqnet_cats
1784     };
1785 
1786     static ei_register_info ei[] = {
1787         { &ei_hiqnet_datatype, { "hiqnet.datatype.invalid", PI_PROTOCOL, PI_WARN, "Invalid datatype", EXPFILL }},
1788     };
1789 
1790     expert_module_t* expert_hiqnet;
1791 
1792     proto_hiqnet = proto_register_protocol ("Harman HiQnet", "HiQnet", "hiqnet");
1793 
1794     proto_register_field_array(proto_hiqnet, hf, array_length(hf));
1795     proto_register_subtree_array(ett, array_length(ett));
1796     expert_hiqnet = expert_register_protocol(proto_hiqnet);
1797     expert_register_field_array(expert_hiqnet, ei, array_length(ei));
1798 }
1799 
1800 
1801 void
proto_reg_handoff_hiqnet(void)1802 proto_reg_handoff_hiqnet(void)
1803 {
1804     static dissector_handle_t hiqnet_udp_handle;
1805     static dissector_handle_t hiqnet_tcp_handle;
1806 
1807     hiqnet_udp_handle = create_dissector_handle(dissect_hiqnet_udp, proto_hiqnet);
1808     hiqnet_tcp_handle = create_dissector_handle(dissect_hiqnet_tcp, proto_hiqnet);
1809     dissector_add_uint_with_preference("udp.port", HIQNET_PORT, hiqnet_udp_handle);
1810     dissector_add_uint_with_preference("tcp.port", HIQNET_PORT, hiqnet_tcp_handle);
1811 }
1812 
1813 /*
1814  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1815  *
1816  * Local variables:
1817  * c-basic-offset: 4
1818  * indent-tabs-mode: nil
1819  * End:
1820  *
1821  * vi: set shiftwidth=4 expandtab:
1822  * :indentSize=4:noTabs=true:
1823  */
1824