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