replace g_malloc and alike by their corresponding ep_ functions
[obnox/wireshark/wip.git] / plugins / profinet / packet-dcerpc-pn-io.c
1 /* packet-dcerpc-pn-io.c
2  * Routines for PROFINET IO dissection.
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 /*
26  * The PN-IO protocol is a field bus protocol related to decentralized 
27  * periphery and is developed by the PROFIBUS Nutzerorganisation e.V. (PNO), 
28  * see: www.profibus.com
29  *
30  *
31  * PN-IO is based on the common DCE-RPC and the "lightweight" PN-RT 
32  * (ethernet type 0x8892) protocols.
33  *
34  * The context manager (CM) part is handling context information 
35  * (like establishing, ...) and is using DCE-RPC as it's underlying 
36  * protocol.
37  *
38  * The actual cyclic data transfer and acyclic notification uses the 
39  * "lightweight" PN-RT protocol.
40  *
41  * There are some other related PROFINET protocols (e.g. PN-DCP, which is 
42  * handling addressing topics).
43  *
44  * Please note: the PROFINET CBA protocol is independant of the PN-IO protocol!
45  */
46
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52
53 #ifdef HAVE_SYS_TYPES_H
54 #include <sys/types.h>
55 #endif
56
57 #include <string.h>
58
59 #include <glib.h>
60 #include <epan/packet.h>
61 #include <epan/dissectors/packet-dcerpc.h>
62
63
64
65 static int proto_pn_io = -1;
66
67 static int hf_pn_io_opnum = -1;
68 static int hf_pn_io_reserved16 = -1;
69
70 static int hf_pn_io_array = -1;
71 static int hf_pn_io_status = -1;
72 static int hf_pn_io_args_max = -1;
73 static int hf_pn_io_args_len = -1;
74 static int hf_pn_io_array_max_count = -1;
75 static int hf_pn_io_array_offset = -1;
76 static int hf_pn_io_array_act_count = -1;
77
78 static int hf_pn_io_data = -1;
79
80 static int hf_pn_io_ar_type = -1;
81 static int hf_pn_io_cminitiator_macadd = -1;
82 static int hf_pn_io_cminitiator_objectuuid = -1;
83 static int hf_pn_io_ar_properties = -1;
84 static int hf_pn_io_cminitiator_activitytimeoutfactor = -1;
85 static int hf_pn_io_cminitiator_udprtport = -1;
86 static int hf_pn_io_station_name_length = -1;
87 static int hf_pn_io_cminitiator_station_name = -1;
88
89 static int hf_pn_io_cmresponder_macadd = -1;
90 static int hf_pn_io_cmresponder_udprtport = -1;
91
92 static int hf_pn_io_iocr_type = -1;
93 static int hf_pn_io_iocr_reference = -1;
94 static int hf_pn_io_lt = -1;
95 static int hf_pn_io_iocr_properties = -1;
96 static int hf_pn_io_data_length = -1;
97 static int hf_pn_io_frame_id = -1;
98 static int hf_pn_io_send_clock_factor = -1;
99 static int hf_pn_io_reduction_ratio = -1;
100 static int hf_pn_io_phase = -1;
101 static int hf_pn_io_sequence = -1;
102 static int hf_pn_io_frame_send_offset = -1;
103 static int hf_pn_io_watchdog_factor = -1;
104 static int hf_pn_io_data_hold_factor = -1;
105 static int hf_pn_io_iocr_tag_header = -1;
106 static int hf_pn_io_iocr_multicast_mac_add = -1;
107 static int hf_pn_io_number_of_apis = -1;
108 static int hf_pn_io_number_of_io_data_objects = -1;
109 static int hf_pn_io_io_data_object_frame_offset = -1;
110 static int hf_pn_io_number_of_iocs = -1;
111 static int hf_pn_io_iocs_frame_offset = -1;
112
113 static int hf_pn_io_alarmcr_type = -1;
114 static int hf_pn_io_alarmcr_properties = -1;
115 static int hf_pn_io_rta_timeoutfactor = -1;
116 static int hf_pn_io_rta_retries = -1;
117 static int hf_pn_io_localalarmref = -1;
118 static int hf_pn_io_maxalarmdatalength = -1;
119 static int hf_pn_io_alarmcr_tagheaderhigh = -1;
120 static int hf_pn_io_alarmcr_tagheaderlow = -1;
121
122 static int hf_pn_io_ar_uuid = -1;
123 static int hf_pn_io_api_tree = -1;
124 static int hf_pn_io_module_tree = -1;
125 static int hf_pn_io_submodule_tree = -1;
126 static int hf_pn_io_io_data_object = -1;
127 static int hf_pn_io_io_cs = -1;
128 static int hf_pn_io_api = -1;
129 static int hf_pn_io_slot_nr = -1;
130 static int hf_pn_io_subslot_nr = -1;
131 static int hf_pn_io_index = -1;
132 static int hf_pn_io_seq_number = -1;
133 static int hf_pn_io_record_data_length = -1;
134 static int hf_pn_io_padding = -1;
135 static int hf_pn_io_add_val1 = -1;
136 static int hf_pn_io_add_val2 = -1;
137
138 static int hf_pn_io_block = -1;
139 static int hf_pn_io_block_header = -1;
140 static int hf_pn_io_block_type = -1;
141 static int hf_pn_io_block_length = -1;
142 static int hf_pn_io_block_version_high = -1;
143 static int hf_pn_io_block_version_low = -1;
144
145 static int hf_pn_io_sessionkey = -1;
146 static int hf_pn_io_control_command = -1;
147 static int hf_pn_io_control_command_prmend = -1;
148 static int hf_pn_io_control_command_applready = -1;
149 static int hf_pn_io_control_command_release = -1;
150 static int hf_pn_io_control_command_done = -1;
151 static int hf_pn_io_control_block_properties = -1;
152
153 static int hf_pn_io_error_code = -1;
154 static int hf_pn_io_error_decode = -1;
155 static int hf_pn_io_error_code1 = -1;
156 static int hf_pn_io_error_code2 = -1;
157 static int hf_pn_io_error_code1_pniorw = -1;
158 static int hf_pn_io_error_code1_pnio = -1;
159
160 static int hf_pn_io_alarm_type = -1;
161 static int hf_pn_io_alarm_specifier = -1;
162 static int hf_pn_io_alarm_specifier_sequence = -1;
163 static int hf_pn_io_alarm_specifier_channel = -1;
164 static int hf_pn_io_alarm_specifier_manufacturer = -1;
165 static int hf_pn_io_alarm_specifier_submodule = -1;
166 static int hf_pn_io_alarm_specifier_ardiagnosis = -1;
167
168 static int hf_pn_io_alarm_dst_endpoint = -1;
169 static int hf_pn_io_alarm_src_endpoint = -1;
170 static int hf_pn_io_pdu_type = -1;
171 static int hf_pn_io_pdu_type_type = -1;
172 static int hf_pn_io_pdu_type_version = -1;
173 static int hf_pn_io_add_flags = -1;
174 static int hf_pn_io_window_size = -1;
175 static int hf_pn_io_tack = -1;
176 static int hf_pn_io_send_seq_num = -1;
177 static int hf_pn_io_ack_seq_num = -1;
178 static int hf_pn_io_var_part_len = -1;
179
180 static int hf_pn_io_number_of_modules = -1;
181 static int hf_pn_io_module_ident_number = -1;
182 static int hf_pn_io_module_properties = -1;
183 static int hf_pn_io_module_state = -1;
184 static int hf_pn_io_number_of_submodules = -1;
185 static int hf_pn_io_submodule_ident_number = -1;
186 static int hf_pn_io_submodule_properties = -1;
187 static int hf_pn_io_submodule_state = -1;
188 static int hf_pn_io_data_description_tree = -1;
189 static int hf_pn_io_data_description = -1;
190 static int hf_pn_io_submodule_data_length = -1;
191 static int hf_pn_io_length_iocs = -1;
192 static int hf_pn_io_length_iops = -1;
193
194 static int hf_pn_io_ioxs = -1;
195 static int hf_pn_io_ioxs_extension = -1;
196 static int hf_pn_io_ioxs_res14 = -1;
197 static int hf_pn_io_ioxs_instance = -1;
198 static int hf_pn_io_ioxs_datastate = -1;
199
200 static int hf_pn_io_address_resolution_properties = -1;
201 static int hf_pn_io_mci_timeout_factor = -1;
202 static int hf_pn_io_provider_station_name = -1;
203
204
205 static gint ett_pn_io = -1;
206 static gint ett_pn_io_block = -1;
207 static gint ett_pn_io_block_header = -1;
208 static gint ett_pn_io_status = -1;
209 static gint ett_pn_io_rtc = -1;
210 static gint ett_pn_io_rta = -1;
211 static gint ett_pn_io_pdu_type = -1;
212 static gint ett_pn_io_add_flags = -1;
213 static gint ett_pn_io_control_command = -1;
214 static gint ett_pn_io_ioxs = -1;
215 static gint ett_pn_io_api = -1;
216 static gint ett_pn_io_data_description = -1;
217 static gint ett_pn_io_module = -1;
218 static gint ett_pn_io_submodule = -1;
219 static gint ett_pn_io_io_data_object = -1;
220 static gint ett_pn_io_io_cs = -1;
221
222 static e_uuid_t uuid_pn_io_device = { 0xDEA00001, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
223 static guint16  ver_pn_io_device = 1;
224
225 static e_uuid_t uuid_pn_io_controller = { 0xDEA00002, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
226 static guint16  ver_pn_io_controller = 1;
227
228 static e_uuid_t uuid_pn_io_supervisor = { 0xDEA00003, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
229 static guint16  ver_pn_io_supervisor = 1;
230
231 static e_uuid_t uuid_pn_io_parameterserver = { 0xDEA00004, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
232 static guint16  ver_pn_io_parameterserver = 1;
233
234
235 static const value_string pn_io_block_type[] = {
236         { 0x0000, "Reserved" },
237         { 0x0001, "Alarm Notification High"},
238         { 0x0002, "Alarm Notification Low"},
239         { 0x0008, "WriteRecordReq"},
240         { 0x8008, "WriteRecordRes"},
241         { 0x0009, "ReadRecordReq"},
242         { 0x8009, "ReadRecordRes"},
243         { 0x0010, "ManufacturerSpecificDiagnosisBlock"},
244         { 0x0011, "ChannelDiagnosisBlock"},
245         { 0x0012, "ExpectedIdentificationDataBlock"},
246         { 0x0014, "SubstituteValue RecordDataRead"},
247         { 0x0015, "RecordInputDataObjectElement"},
248         { 0x0016, "RecordOutputDataObjectElement"},
249         { 0x0017, "RecordOutputDataSubstituteObjectElement"},
250         { 0x0018, "ARData"},
251         { 0x0019, "LogData"},
252         { 0x001A, "APIData"},
253         { 0x0020, "I&M0"},
254         { 0x0021, "I&M1"},
255         { 0x0022, "I&M2"},
256         { 0x0023, "I&M3"},
257         { 0x0024, "I&M4"},
258         { 0x8001, "Alarm Ack High"},
259         { 0x8002, "Alarm Ack Low"},
260         { 0x0101, "ARBlockReq"},
261         { 0x8101, "ARBlockRes"},
262         { 0x0102, "IOCRBlockReq"},
263         { 0x8102, "IOCRBlockRes"},
264         { 0x0103, "AlarmCRBlockReq"},
265         { 0x8103, "AlarmCRBlockRes"},
266         { 0x0104, "ExpectedSubmoduleBlockReq"},
267         { 0x8104, "ModuleDiffBlock"},
268         { 0x0105, "PrmServerBlockReq"},
269         { 0x8105, "PrmServerBlockRes"},
270         { 0x0106, "MCRBlockReq"},
271         { 0x0110, "IODBlockReq"},
272         { 0x8110, "IODBlockRes"},
273         { 0x0111, "IODBlockReq"},
274         { 0x8111, "IODBlockRes"},
275         { 0x0112, "IOXBlockReq"},
276         { 0x8112, "IOXBlockRes"},
277         { 0x0113, "IOXBlockReq"},
278         { 0x8113, "IOXBlockRes"},
279         { 0x0114, "ReleaseBlockReq"},
280         { 0x8114, "ReleaseBlockRes"},
281         { 0, NULL }
282 };
283
284 static const value_string pn_io_alarm_type[] = {
285         { 0x0000, "Reserved" },
286         { 0x0001, "Diagnosis" },
287         { 0x0002, "Process" },
288         { 0x0003, "Pull" },
289         { 0x0004, "Plug" },
290         { 0x0005, "Status" },
291         { 0x0006, "Update" },
292         { 0x0007, "Redundancy" },
293         { 0x0008, "Controlled by supervisor" },
294         { 0x0009, "Released by supervisor" },
295         { 0x000A, "Plug wrong submodule" },
296         { 0x000B, "Return of submodule" },
297     /* 0x000C - 0x001F reserved */
298     /* 0x0020 - 0x007F manufacturer specific */
299     /* 0x0080 - 0x00FF reserved for profiles */
300     /* 0x0100 - 0xFFFF reserved */
301     { 0, NULL }
302 };
303
304 static const value_string pn_io_pdu_type[] = {
305         { 0x01, "Data-RTA-PDU" },
306         { 0x02, "NACK-RTA-PDU" },
307         { 0x03, "ACK-RTA-PDU" },
308         { 0x04, "ERR-RTA-PDU" },
309     { 0, NULL }
310 };
311
312 static const value_string pn_io_error_code[] = {
313         { 0x00, "OK" },
314         { 0x81, "PNIO" },
315         { 0xCF, "RTA error" },
316         { 0xDA, "AlarmAck" },
317         { 0xDB, "IODConnectRes" },
318         { 0xDC, "IODReleaseRes" },
319         { 0xDD, "IODControlRes" },
320         { 0xDE, "IODReadRes" },
321         { 0xDF, "IODWriteRes" },
322     { 0, NULL }
323 };
324
325 static const value_string pn_io_error_decode[] = {
326         { 0x00, "OK" },
327         { 0x80, "PNIORW" },
328         { 0x81, "PNIO" },
329     { 0, NULL }
330 };
331
332 /*
333 XXX: the next 2 are dependant on error_code and error_decode
334
335 e.g.: CL-RPC error:
336 error_code .. see above
337 error_decode .. 0x81
338 error_code1 .. 0x69
339 error_code2 ..
340 1 RPC_ERR_REJECTED
341 2 RPC_ERR_FAULTED
342 3 RPC_ERR_TIMEOUT
343 4 RPC_ERR_IN_ARGS
344 5 RPC_ERR_OUT_ARGS
345 6 RPC_ERR_DECODE
346 7 RPC_ERR_PNIO_OUT_ARGS
347 8 Application Timeout
348 */
349
350 /* XXX: add some more error codes here */
351 static const value_string pn_io_error_code1[] = {
352         { 0x00, "OK" },
353     { 0, NULL }
354 };
355
356 /* XXX: add some more error codes here */
357 static const value_string pn_io_error_code2[] = {
358         { 0x00, "OK" },
359     { 0, NULL }
360 };
361
362 static const value_string pn_io_error_code1_pniorw[] = {
363         { 0x0a /* 10*/, "application" },
364         { 0x0b /* 11*/, "access" },
365         { 0x0c /* 12*/, "resource" },
366         { 0x0d /* 13*/, "user specific(13)" },
367         { 0x0e /* 14*/, "user specific(14)" },
368         { 0x0f /* 15*/, "user specific(15)" },
369     { 0, NULL }
370 };
371
372 static const value_string pn_io_error_code1_pnio[] = {
373         { 0x00 /*  0*/, "Reserved" },
374         { 0x01 /*  1*/, "Connect: Faulty ARBlockReq" },
375         { 0x02 /*  2*/, "Connect: Faulty IOCRBlockReq" },
376         { 0x03 /*  3*/, "Connect: Faulty ExpectedSubmoduleBlockReq" },
377         { 0x04 /*  4*/, "Connect: Faulty AlarmCRBlockReq" },
378         { 0x05 /*  5*/, "Connect: Faulty PrmServerBlockReq" },
379
380         { 0x14 /* 20*/, "IODControl: Faulty ControlBlockConnect" },
381         { 0x15 /* 21*/, "IODControl: Faulty ControlBlockPlug" },
382         { 0x16 /* 22*/, "IOXControl: Faulty ControlBlock after a connect est." },
383         { 0x17 /* 23*/, "IOXControl: Faulty ControlBlock a plug alarm" },
384
385     { 0x28 /* 40*/, "Release: Faulty ReleaseBlock" },
386
387     { 0x3c /* 60*/, "AlarmAck Error Codes" },
388     { 0x3d /* 61*/, "CMDEV" },
389     { 0x3e /* 62*/, "CMCTL" },
390     { 0x3f /* 63*/, "NRPM" },
391     { 0x40 /* 64*/, "RMPM" },
392     { 0x41 /* 65*/, "ALPMI" },
393     { 0x42 /* 66*/, "ALPMR" },
394     { 0x43 /* 67*/, "LMPM" },
395     { 0x44 /* 68*/, "MMAC" },
396     { 0x45 /* 69*/, "RPC" },
397     { 0x46 /* 70*/, "APMR" },
398     { 0x47 /* 71*/, "APMS" },
399     { 0x48 /* 72*/, "CPM" },
400     { 0x49 /* 73*/, "PPM" },
401     { 0x4a /* 74*/, "DCPUCS" },
402     { 0x4b /* 75*/, "DCPUCR" },
403     { 0x4c /* 76*/, "DCPMCS" },
404     { 0x4d /* 77*/, "DCPMCR" },
405     { 0x4e /* 78*/, "FSPM" },
406         { 0xfd /*253*/, "RTA_ERR_CLS_PROTOCOL" },
407     { 0, NULL }
408 };
409
410 static const value_string pn_io_ioxs[] = {
411         { 0x00 /*  0*/, "detected by subslot" },
412         { 0x01 /*  1*/, "detected by slot" },
413         { 0x02 /*  2*/, "detected by IO device" },
414         { 0x03 /*  3*/, "detected by IO controller" },
415     { 0, NULL }
416 };
417
418
419 static const value_string pn_io_ar_type[] = {
420         { 0x0000, "reserved" },
421         { 0x0001, "IOCARSingle" },
422         { 0x0002, "reserved" },
423         { 0x0003, "IOCARCIR" },
424         { 0x0004, "IOCAR_IOControllerRedundant" },
425         { 0x0005, "IOCAR_IODeviceRedundant" },
426         { 0x0006, "IOSAR" },
427     /*0x0007 - 0xFFFF reserved */
428     { 0, NULL }
429 };
430
431 static const value_string pn_io_iocr_type[] = {
432         { 0x0000, "reserved" },
433         { 0x0001, "Input CR" },
434         { 0x0002, "Output CR" },
435         { 0x0003, "Multicast Provider CR" },
436         { 0x0004, "Multicast Consumer CR" },
437     /*0x0005 - 0xFFFF reserved */
438     { 0, NULL }
439 };
440
441
442 static const value_string pn_io_data_description[] = {
443         { 0x0000, "reserved" },
444         { 0x0001, "Input" },
445         { 0x0002, "Output" },
446         { 0x0003, "reserved" },
447     /*0x0004 - 0xFFFF reserved */
448     { 0, NULL }
449 };
450
451
452
453 static const value_string pn_io_module_state[] = {
454         { 0x0000, "no module" },
455         { 0x0001, "wrong module" },
456         { 0x0002, "proper module" },
457         { 0x0003, "substitute" },
458     /*0x0004 - 0xFFFF reserved */
459     { 0, NULL }
460 };
461
462
463
464
465
466
467 /* dissect a 6 byte MAC address */
468 static int 
469 dissect_MAC(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
470                     proto_tree *tree, int hfindex, guint8 *pdata)
471 {
472     guint8 data[6];
473
474     tvb_memcpy(tvb, data, offset, 6);
475     if(tree)
476         proto_tree_add_ether(tree, hfindex, tvb, offset, 6, data);
477
478     if (pdata)
479         memcpy(pdata, data, 6);
480
481     return offset + 6;
482 }
483
484
485
486
487
488 /* dissect the four status (error) fields */
489 static int
490 dissect_PNIO_status(tvbuff_t *tvb, int offset,
491         packet_info *pinfo, proto_tree *tree, guint8 *drep)
492 {
493     guint8  u8ErrorCode;
494     guint8  u8ErrorDecode;
495     guint8  u8ErrorCode1;
496     guint8  u8ErrorCode2;
497
498     proto_item *sub_item;
499         proto_tree *sub_tree;
500         guint32 u32SubStart;
501     int bytemask = (drep[0] & 0x10) ? 3 : 0;
502     const value_string *error_code1_vals;
503
504
505
506     /* status */
507     sub_item = proto_tree_add_item(tree, hf_pn_io_status, tvb, offset, 0, FALSE);
508         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_status);
509     u32SubStart = offset;
510
511     /* the PNIOStatus field is existing in both the RPC and the application data,
512      * depending on the current PDU.
513      * As the byte representation of these layers are different, this has to be handled
514      * in a somewhat different way than elsewhere. */
515
516     dissect_dcerpc_uint8(tvb, offset+(0^bytemask), pinfo, sub_tree, drep, 
517                         hf_pn_io_error_code, &u8ErrorCode);
518         dissect_dcerpc_uint8(tvb, offset+(1^bytemask), pinfo, sub_tree, drep, 
519                         hf_pn_io_error_decode, &u8ErrorDecode);
520
521     switch(u8ErrorDecode) {
522     case(0x80): /* PNIORW */
523             dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep, 
524                             hf_pn_io_error_code1_pniorw, &u8ErrorCode1);
525         error_code1_vals = pn_io_error_code1_pniorw;
526         break;
527     case(0x81): /* PNIO */
528             dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep, 
529                             hf_pn_io_error_code1_pnio, &u8ErrorCode1);
530         error_code1_vals = pn_io_error_code1_pnio;
531         break;
532     default:
533             dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep, 
534                             hf_pn_io_error_code1, &u8ErrorCode1);
535         error_code1_vals = pn_io_error_code1;
536     }
537
538     /* XXX - this has to be decode specific too */
539         dissect_dcerpc_uint8(tvb, offset+(3^bytemask), pinfo, sub_tree, drep, 
540                         hf_pn_io_error_code2, &u8ErrorCode2);
541
542     offset +=4;
543
544     if(u8ErrorCode == 0 && u8ErrorDecode == 0 && u8ErrorCode1 == 0 && u8ErrorCode2 == 0) {
545         proto_item_append_text(sub_item, ": OK");
546         if (check_col(pinfo->cinfo, COL_INFO))
547                 col_append_str(pinfo->cinfo, COL_INFO, ", OK");
548     } else {
549         proto_item_append_text(sub_item, ": Error Code: \"%s\", Decode: \"%s\", Code1: \"%s\" Code2: 0x%x", 
550             val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"),
551             val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"),
552             val_to_str(u8ErrorCode1, error_code1_vals, "(0x%x)"),
553             u8ErrorCode2);
554         if (check_col(pinfo->cinfo, COL_INFO))
555                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Error Code: %s, Decode: %s, Code1: 0x%x Code2: 0x%x",
556             val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"),
557             val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"),
558             u8ErrorCode1,
559             u8ErrorCode2);
560     }
561         proto_item_set_len(sub_item, offset - u32SubStart);
562
563     return offset;
564 }
565
566
567 /* dissect the alarm specifier */
568 static int
569 dissect_Alarm_specifier(tvbuff_t *tvb, int offset,
570         packet_info *pinfo, proto_tree *tree, guint8 *drep)
571 {
572     guint16 u16AlarmSpecifierSequence;
573     guint16 u16AlarmSpecifierChannel;
574     guint16 u16AlarmSpecifierManufacturer;
575     guint16 u16AlarmSpecifierSubmodule;
576     guint16 u16AlarmSpecifierAR;
577     proto_item *sub_item;
578         proto_tree *sub_tree;
579
580     /* alarm specifier */
581         sub_item = proto_tree_add_item(tree, hf_pn_io_alarm_specifier, tvb, offset, 2, FALSE);
582         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type);
583
584         dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
585                         hf_pn_io_alarm_specifier_sequence, &u16AlarmSpecifierSequence);
586     u16AlarmSpecifierSequence &= 0x07FF;
587         dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
588                         hf_pn_io_alarm_specifier_channel, &u16AlarmSpecifierChannel);
589     u16AlarmSpecifierChannel = (u16AlarmSpecifierChannel &0x0800) >> 11;
590         dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
591                         hf_pn_io_alarm_specifier_manufacturer, &u16AlarmSpecifierManufacturer);
592     u16AlarmSpecifierManufacturer = (u16AlarmSpecifierManufacturer &0x1000) >> 12;
593         dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
594                         hf_pn_io_alarm_specifier_submodule, &u16AlarmSpecifierSubmodule);
595     u16AlarmSpecifierSubmodule = (u16AlarmSpecifierSubmodule & 0x2000) >> 13;
596         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
597                         hf_pn_io_alarm_specifier_ardiagnosis, &u16AlarmSpecifierAR);
598     u16AlarmSpecifierAR = (u16AlarmSpecifierAR & 0x8000) >> 15;
599
600
601     proto_item_append_text(sub_item, ", Sequence: %u, Channel: %u, Manuf: %u, Submodule: %u AR: %u", 
602         u16AlarmSpecifierSequence, u16AlarmSpecifierChannel, 
603         u16AlarmSpecifierManufacturer, u16AlarmSpecifierSubmodule, u16AlarmSpecifierAR);
604
605     return offset;
606 }
607
608
609 /* dissect the alarm header */
610 static int
611 dissect_Alarm_header(tvbuff_t *tvb, int offset,
612         packet_info *pinfo, proto_tree *tree, guint8 *drep)
613 {
614     guint16 u16AlarmType;
615     guint32 u32Api;
616     guint16 u16SlotNr;
617     guint16 u16SubslotNr;
618
619         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
620                         hf_pn_io_alarm_type, &u16AlarmType);
621         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
622                         hf_pn_io_api, &u32Api);
623         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
624                         hf_pn_io_slot_nr, &u16SlotNr);
625         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
626                         hf_pn_io_subslot_nr, &u16SubslotNr);
627
628     if (check_col(pinfo->cinfo, COL_INFO))
629             col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Slot: 0x%x/0x%x", 
630         val_to_str(u16AlarmType, pn_io_alarm_type, "Unknown"),
631         u16SlotNr, u16SubslotNr);
632
633     return offset;
634 }
635
636
637 /* dissect the alarm note block */
638 static int
639 dissect_Alarm_note_block(tvbuff_t *tvb, int offset,
640         packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 body_length)
641 {
642     guint32 u32ModuleIdentNumber;
643     guint32 u32SubmoduleIdentNumber;
644
645     if (check_col(pinfo->cinfo, COL_INFO))
646             col_append_str(pinfo->cinfo, COL_INFO, ", Alarm Notification");
647
648     offset = dissect_Alarm_header(tvb, offset, pinfo, tree, drep);
649     
650         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
651                         hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
652         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
653                         hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
654
655     offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep);
656
657     /* XXX - dissect AlarmItem */
658     body_length -= 20;
659     proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, body_length, "data", 
660         "Alarm Item Data: %u bytes", body_length);
661     offset += body_length;
662
663     return offset;
664 }
665
666
667 /* dissect the alarm acknowledge block */
668 static int
669 dissect_Alarm_ack_block(tvbuff_t *tvb, int offset,
670         packet_info *pinfo, proto_tree *tree, guint8 *drep)
671 {
672     if (check_col(pinfo->cinfo, COL_INFO))
673             col_append_str(pinfo->cinfo, COL_INFO, ", Alarm Ack");
674
675     offset = dissect_Alarm_header(tvb, offset, pinfo, tree, drep);
676
677     offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep);
678
679     offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
680
681     return offset;
682 }
683
684
685 /* dissect the read/write header */
686 static int
687 dissect_ReadWrite_header(tvbuff_t *tvb, int offset,
688         packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index)
689 {
690     e_uuid_t uuid;
691     guint32 u32Api;
692     guint16 u16SlotNr;
693     guint16 u16SubslotNr;
694     guint16 u16SeqNr;
695
696         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
697                         hf_pn_io_seq_number, &u16SeqNr);
698
699     offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, 
700                         hf_pn_io_ar_uuid, &uuid);
701
702         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
703                         hf_pn_io_api, &u32Api);
704         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
705                         hf_pn_io_slot_nr, &u16SlotNr);
706         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
707                         hf_pn_io_subslot_nr, &u16SubslotNr);
708     proto_tree_add_string_format(tree, hf_pn_io_padding, tvb, offset, 2, "padding", "Padding: 2 bytes");
709     offset += 2;
710         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
711                         hf_pn_io_index, u16Index);
712
713     if (check_col(pinfo->cinfo, COL_INFO))
714             col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: 0x%x, Slot: 0x%x/0x%x",
715             u32Api, u16SlotNr, u16SubslotNr);
716
717     return offset;
718 }
719
720
721 /* dissect the read/write request block */
722 static int
723 dissect_ReadWrite_rqst_block(tvbuff_t *tvb, int offset,
724         packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen)
725 {
726
727     offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, drep, u16Index);
728
729         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
730                         hf_pn_io_record_data_length, u32RecDataLen);
731     /* XXX: don't know how to handle the optional TargetARUUID */
732
733     if (check_col(pinfo->cinfo, COL_INFO))
734             col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes",
735             *u32RecDataLen);
736
737     return offset;
738 }
739
740
741 /* dissect the read/write response block */
742 static int
743 dissect_ReadWrite_resp_block(tvbuff_t *tvb, int offset,
744         packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index)
745 {
746     guint32 u32RecDataLen;
747     guint16 u16AddVal1;
748     guint16 u16AddVal2;
749
750
751     offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, drep, u16Index);
752
753         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
754                         hf_pn_io_record_data_length, &u32RecDataLen);
755
756         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
757                         hf_pn_io_add_val1, &u16AddVal1);
758
759         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
760                         hf_pn_io_add_val2, &u16AddVal2);
761
762     if (check_col(pinfo->cinfo, COL_INFO))
763             col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes",
764             u32RecDataLen);
765
766     return offset;
767 }
768
769
770 /* dissect the control/connect block */
771 static int
772 dissect_ControlConnect_block(tvbuff_t *tvb, int offset,
773         packet_info *pinfo, proto_tree *tree, guint8 *drep)
774 {
775     e_uuid_t    ar_uuid;
776         proto_item *sub_item;
777         proto_tree *sub_tree;
778     guint16     u16PrmEnd;
779     guint16     u16ApplReady;
780     guint16     u16Release;
781     guint16     u16CmdDone;
782
783
784     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
785                         hf_pn_io_reserved16, NULL);
786
787     offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, 
788                         hf_pn_io_ar_uuid, &ar_uuid);
789
790     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
791                         hf_pn_io_sessionkey, NULL);
792
793     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
794                         hf_pn_io_reserved16, NULL);
795
796     sub_item = proto_tree_add_item(tree, hf_pn_io_control_command, tvb, offset, 2, FALSE);
797         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_control_command);
798
799     dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
800                         hf_pn_io_control_command_prmend, &u16PrmEnd);
801     if(u16PrmEnd & 0x0001) {
802         proto_item_append_text(sub_item, ", Parameter End");
803         if (check_col(pinfo->cinfo, COL_INFO))
804                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Parameter End\"");
805     }
806     dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
807                         hf_pn_io_control_command_applready, &u16ApplReady);
808     if((u16ApplReady >> 1) & 0x0001) {
809         proto_item_append_text(sub_item, ", Application Ready");
810         if (check_col(pinfo->cinfo, COL_INFO))
811                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Application Ready\"");
812     }
813     dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
814                         hf_pn_io_control_command_release, &u16Release);
815     if((u16Release >> 2) & 0x0001) {
816         proto_item_append_text(sub_item, ", Release");
817         if (check_col(pinfo->cinfo, COL_INFO))
818                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Release\"");
819     }
820     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
821                         hf_pn_io_control_command_done, &u16CmdDone);
822     if((u16CmdDone >> 3) & 0x0001) {
823         proto_item_append_text(sub_item, ", Done");
824         if (check_col(pinfo->cinfo, COL_INFO))
825                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Done\"");
826     }
827
828     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
829                         hf_pn_io_control_block_properties, NULL);
830
831     return offset;
832 }
833
834
835 /* dissect the ARBlockReq */
836 static int
837 dissect_ARBlockReq(tvbuff_t *tvb, int offset,
838         packet_info *pinfo, proto_tree *tree, guint8 *drep)
839 {
840     guint16 u16ARType;
841     e_uuid_t uuid;
842     guint16 u16SessionKey;
843     guint8 mac[6];
844     guint32 u32ARProperties;
845     guint16 u16TimeoutFactor;
846     guint16 u16UDPRTPort;
847     guint16 u16NameLength;
848     guint8 *pu8StationName;
849
850
851         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
852                         hf_pn_io_ar_type, &u16ARType);
853     offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, 
854                         hf_pn_io_ar_uuid, &uuid);
855         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
856                         hf_pn_io_sessionkey, &u16SessionKey);
857     offset = dissect_MAC(tvb, offset, pinfo, tree, 
858                         hf_pn_io_cminitiator_macadd, mac);
859     offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, 
860                         hf_pn_io_cminitiator_objectuuid, &uuid);
861         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
862                         hf_pn_io_ar_properties, &u32ARProperties);
863         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
864                         hf_pn_io_cminitiator_activitytimeoutfactor, &u16TimeoutFactor);   /* XXX - special values */
865         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
866                         hf_pn_io_cminitiator_udprtport, &u16UDPRTPort);   /* XXX - special values */
867         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
868                         hf_pn_io_station_name_length, &u16NameLength);
869
870     pu8StationName = ep_alloc(u16NameLength+1);
871     tvb_memcpy(tvb, pu8StationName, offset, u16NameLength);
872     pu8StationName[u16NameLength] = '\0';
873     proto_tree_add_string (tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, pu8StationName);
874     offset += u16NameLength;
875
876     /*if (check_col(pinfo->cinfo, COL_INFO))
877             col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: %u, Slot: %u/%u",
878             u32Api, u16SlotNr, u16SubslotNr);*/
879
880     return offset;
881 }
882
883
884 /* dissect the ARBlockRes */
885 static int
886 dissect_ARBlockRes(tvbuff_t *tvb, int offset,
887         packet_info *pinfo, proto_tree *tree, guint8 *drep)
888 {
889     guint16 u16ARType;
890     e_uuid_t uuid;
891     guint16 u16SessionKey;
892     guint8 mac[6];
893     guint16 u16UDPRTPort;
894
895
896         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
897                         hf_pn_io_ar_type, &u16ARType);
898     offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, 
899                         hf_pn_io_ar_uuid, &uuid);
900         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
901                         hf_pn_io_sessionkey, &u16SessionKey);
902     offset = dissect_MAC(tvb, offset, pinfo, tree, 
903                         hf_pn_io_cmresponder_macadd, mac);
904         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
905                         hf_pn_io_cmresponder_udprtport, &u16UDPRTPort);   /* XXX - special values */
906
907     /*if (check_col(pinfo->cinfo, COL_INFO))
908             col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: %u, Slot: %u/%u",
909             u32Api, u16SlotNr, u16SubslotNr);*/
910
911     return offset;
912 }
913
914
915 /* dissect the IOCRBlockReq */
916 static int
917 dissect_IOCRBlockReq(tvbuff_t *tvb, int offset,
918         packet_info *pinfo, proto_tree *tree, guint8 *drep)
919 {
920     guint16 u16IOCRType;
921     guint16 u16IOCRReference;
922     guint16 u16LT;
923     guint32 u32IOCRProperties;
924     guint16 u16DataLength;
925     guint16 u16FrameID;
926     guint16 u16SendClockFactor;
927     guint16 u16ReductionRatio;
928     guint16 u16Phase;
929     guint16 u16Sequence;
930     guint32 u32FrameSendOffset;
931     guint16 u16WatchdogFactor;
932     guint16 u16DataHoldFactor;
933     guint16 u16IOCRTagHeader;
934     guint8 mac[6];
935     guint16 u16NumberOfAPIs;
936     guint32 u32Api;
937     guint16 u16NumberOfIODataObjects;
938     guint16 u16SlotNr;
939     guint16 u16SubslotNr;
940     guint16 u16IODataObjectFrameOffset;
941     guint16 u16NumberOfIOCS;
942     guint16 u16IOCSFrameOffset;
943     proto_item *api_item;
944         proto_tree *api_tree;
945         guint32 u32ApiStart;
946     guint16 u16Tmp;
947     proto_item *sub_item;
948         proto_tree *sub_tree;
949         guint32 u32SubStart;
950
951
952         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
953                         hf_pn_io_iocr_type, &u16IOCRType);
954         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
955                         hf_pn_io_iocr_reference, &u16IOCRReference);
956         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
957                         hf_pn_io_lt, &u16LT);
958         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
959                         hf_pn_io_iocr_properties, &u32IOCRProperties);
960         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
961                         hf_pn_io_data_length, &u16DataLength);
962         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
963                         hf_pn_io_frame_id, &u16FrameID);
964         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
965                         hf_pn_io_send_clock_factor, &u16SendClockFactor);
966         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
967                         hf_pn_io_reduction_ratio, &u16ReductionRatio);
968         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
969                         hf_pn_io_phase, &u16Phase);
970         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
971                         hf_pn_io_sequence, &u16Sequence);
972         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
973                         hf_pn_io_frame_send_offset, &u32FrameSendOffset);
974         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
975                         hf_pn_io_watchdog_factor, &u16WatchdogFactor);
976         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
977                         hf_pn_io_data_hold_factor, &u16DataHoldFactor);
978         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
979                         hf_pn_io_iocr_tag_header, &u16IOCRTagHeader);
980     offset = dissect_MAC(tvb, offset, pinfo, tree, 
981                         hf_pn_io_iocr_multicast_mac_add, mac);
982
983         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
984                         hf_pn_io_number_of_apis, &u16NumberOfAPIs);
985     while(u16NumberOfAPIs--) {
986         api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
987             api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
988         u32ApiStart = offset;
989
990         /* API */
991             offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, 
992                             hf_pn_io_api, &u32Api);
993         /* NumberOfIODataObjects */
994             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
995                             hf_pn_io_number_of_io_data_objects, &u16NumberOfIODataObjects);
996
997         u16Tmp = u16NumberOfIODataObjects;
998         while(u16Tmp--) {
999             sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_data_object, tvb, offset, 0, FALSE);
1000                 sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_data_object);
1001             u32SubStart = offset;
1002
1003             /* SlotNumber */
1004                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1005                                 hf_pn_io_slot_nr, &u16SlotNr);
1006             /* Subslotnumber */
1007                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1008                                 hf_pn_io_subslot_nr, &u16SubslotNr);
1009             /* IODataObjectFrameOffset */
1010                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1011                                 hf_pn_io_io_data_object_frame_offset, &u16IODataObjectFrameOffset);
1012
1013             proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u", 
1014                 u16SlotNr, u16SubslotNr, u16IODataObjectFrameOffset);
1015
1016                 proto_item_set_len(sub_item, offset - u32SubStart);
1017         }
1018         /* NumberOfIOCS */
1019             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
1020                             hf_pn_io_number_of_iocs, &u16NumberOfIOCS);
1021
1022         u16Tmp = u16NumberOfIOCS;
1023         while(u16Tmp--) {
1024             sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_cs, tvb, offset, 0, FALSE);
1025                 sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_cs);
1026             u32SubStart = offset;
1027
1028             /* SlotNumber */
1029                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1030                                 hf_pn_io_slot_nr, &u16SlotNr);
1031             /* Subslotnumber */
1032                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1033                                 hf_pn_io_subslot_nr, &u16SubslotNr);
1034             /* IOCSFrameOffset */
1035                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1036                                 hf_pn_io_iocs_frame_offset, &u16IOCSFrameOffset);
1037
1038             proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u", 
1039                 u16SlotNr, u16SubslotNr, u16IOCSFrameOffset);
1040
1041                 proto_item_set_len(sub_item, offset - u32SubStart);
1042         }
1043
1044         proto_item_append_text(api_item, ": %u, NumberOfIODataObjects: %u NumberOfIOCS: %u", 
1045             u32Api, u16NumberOfIODataObjects, u16NumberOfIOCS);
1046
1047             proto_item_set_len(api_item, offset - u32ApiStart);
1048     }
1049
1050     return offset;
1051 }
1052
1053
1054 /* dissect the AlarmCRBlockReq */
1055 static int
1056 dissect_AlarmCRBlockReq(tvbuff_t *tvb, int offset,
1057         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1058 {
1059     guint16 u16AlarmCRType;
1060     guint16 u16LT;
1061     guint32 u32AlarmCRProperties;
1062     guint16 u16RTATimeoutFactor;
1063     guint16 u16RTARetries;
1064     guint16 u16LocalAlarmReference;
1065     guint16 u16MaxAlarmDataLength;
1066     guint16 u16AlarmCRTagHeaderHigh;
1067     guint16 u16AlarmCRTagHeaderLow;
1068
1069
1070         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1071                         hf_pn_io_alarmcr_type, &u16AlarmCRType);
1072         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1073                         hf_pn_io_lt, &u16LT);
1074         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
1075                         hf_pn_io_alarmcr_properties, &u32AlarmCRProperties);
1076         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1077                         hf_pn_io_rta_timeoutfactor, &u16RTATimeoutFactor);
1078         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1079                         hf_pn_io_rta_retries, &u16RTARetries);
1080         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1081                         hf_pn_io_localalarmref, &u16LocalAlarmReference);
1082         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1083                         hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength);
1084         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1085                         hf_pn_io_alarmcr_tagheaderhigh, &u16AlarmCRTagHeaderHigh);
1086         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1087                         hf_pn_io_alarmcr_tagheaderlow, &u16AlarmCRTagHeaderLow);
1088
1089     return offset;
1090 }
1091
1092
1093 /* dissect the AlarmCRBlockRes */
1094 static int
1095 dissect_AlarmCRBlockRes(tvbuff_t *tvb, int offset,
1096         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1097 {
1098     guint16 u16AlarmCRType;
1099     guint16 u16LocalAlarmReference;
1100     guint16 u16MaxAlarmDataLength;
1101
1102
1103         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1104                         hf_pn_io_alarmcr_type, &u16AlarmCRType);
1105         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1106                         hf_pn_io_localalarmref, &u16LocalAlarmReference);
1107         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1108                         hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength);
1109
1110     return offset;
1111 }
1112
1113
1114
1115 /* dissect the IOCRBlockRes */
1116 static int
1117 dissect_IOCRBlockRes(tvbuff_t *tvb, int offset,
1118         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1119 {
1120     guint16 u16IOCRType;
1121     guint16 u16IOCRReference;
1122     guint16 u16FrameID;
1123
1124
1125         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1126                         hf_pn_io_iocr_type, &u16IOCRType);
1127         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1128                         hf_pn_io_iocr_reference, &u16IOCRReference);
1129         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1130                         hf_pn_io_frame_id, &u16FrameID);
1131
1132     return offset;
1133 }
1134
1135
1136
1137 /* dissect the MCRBlockReq */
1138 static int
1139 dissect_MCRBlockReq(tvbuff_t *tvb, int offset,
1140         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1141 {
1142     guint16 u16IOCRReference;
1143     guint32 u32AddressResolutionProperties;
1144     guint16 u16MCITimeoutFactor;
1145     guint16 u16NameLength;
1146     guint8 *pu8StationName;
1147
1148
1149         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1150                         hf_pn_io_iocr_reference, &u16IOCRReference);
1151         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, 
1152                         hf_pn_io_address_resolution_properties, &u32AddressResolutionProperties);
1153         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1154                         hf_pn_io_mci_timeout_factor, &u16MCITimeoutFactor);
1155
1156         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1157                         hf_pn_io_station_name_length, &u16NameLength);
1158
1159     pu8StationName = ep_alloc(u16NameLength+1);
1160     tvb_memcpy(tvb, pu8StationName, offset, u16NameLength);
1161     pu8StationName[u16NameLength] = '\0';
1162     proto_tree_add_string (tree, hf_pn_io_provider_station_name, tvb, offset, u16NameLength, pu8StationName);
1163     offset += u16NameLength;    
1164
1165     return offset;
1166 }
1167
1168
1169
1170 /* dissect the DataDescription */
1171 static int
1172 dissect_DataDescription(tvbuff_t *tvb, int offset,
1173         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1174 {
1175     guint16 u16DataDescription;
1176     guint16 u16SubmoduleDataLength;
1177     guint8  u8LengthIOCS;
1178     guint8  u8LengthIOPS;
1179     proto_item *sub_item;
1180         proto_tree *sub_tree;
1181         guint32 u32SubStart;
1182
1183
1184     sub_item = proto_tree_add_item(tree, hf_pn_io_data_description_tree, tvb, offset, 0, FALSE);
1185         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_data_description);
1186     u32SubStart = offset;
1187
1188     /* DataDescription */
1189         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1190                     hf_pn_io_data_description, &u16DataDescription);
1191     /* SubmoduleDataLength */
1192         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1193                     hf_pn_io_submodule_data_length, &u16SubmoduleDataLength);
1194     /* LengthIOCS */
1195         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1196                     hf_pn_io_length_iocs, &u8LengthIOCS);
1197     /* LengthIOPS */
1198         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1199                     hf_pn_io_length_iops, &u8LengthIOPS);
1200
1201     proto_item_append_text(sub_item, ": %s, SubmoduleDataLength: %u, LengthIOCS: %u, u8LengthIOPS: %u", 
1202         val_to_str(u16DataDescription, pn_io_data_description, "(0x%x)"), 
1203         u16SubmoduleDataLength, u8LengthIOCS, u8LengthIOPS);
1204         proto_item_set_len(sub_item, offset - u32SubStart);
1205
1206     return offset;
1207 }
1208
1209
1210 /* dissect the ExpectedSubmoduleBlockReq */
1211 static int
1212 dissect_ExpectedSubmoduleBlockReq(tvbuff_t *tvb, int offset,
1213         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1214 {
1215     guint16 u16NumberOfAPIs;
1216     guint32 u32Api;
1217     guint16 u16SlotNr;
1218     guint32 u32ModuleIdentNumber;
1219     guint16 u16ModuleProperties;
1220     guint16 u16NumberOfSubmodules;
1221     guint16 u16SubslotNr;
1222     guint32 u32SubmoduleIdentNumber;
1223     guint16 u16SubmoduleProperties;
1224     proto_item *api_item;
1225         proto_tree *api_tree;
1226         guint32 u32ApiStart;
1227     proto_item *sub_item;
1228         proto_tree *sub_tree;
1229         guint32 u32SubStart;
1230
1231
1232         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1233                         hf_pn_io_number_of_apis, &u16NumberOfAPIs);
1234     while(u16NumberOfAPIs--) {
1235         api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
1236             api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
1237         u32ApiStart = offset;
1238
1239         /* API */
1240             offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, 
1241                             hf_pn_io_api, &u32Api);
1242         /* SlotNumber */
1243             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
1244                             hf_pn_io_slot_nr, &u16SlotNr);
1245         /* ModuleIdentNumber */
1246             offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, 
1247                             hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
1248         /* ModuleProperties */
1249             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
1250                             hf_pn_io_module_properties, &u16ModuleProperties);
1251         /* NumberOfSubmodules */
1252             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
1253                             hf_pn_io_number_of_submodules, &u16NumberOfSubmodules);
1254
1255         proto_item_append_text(api_item, ": %u, Slot: 0x%x, ModuleIdentNumber: 0x%x ModuleProperties: 0x%x NumberOfSubmodules: %u", 
1256             u32Api, u16SlotNr, u32ModuleIdentNumber, u16ModuleProperties, u16NumberOfSubmodules);
1257
1258         while(u16NumberOfSubmodules--) {
1259             sub_item = proto_tree_add_item(api_tree, hf_pn_io_submodule_tree, tvb, offset, 0, FALSE);
1260                 sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule);
1261             u32SubStart = offset;
1262
1263             /* Subslotnumber */
1264                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1265                                 hf_pn_io_subslot_nr, &u16SubslotNr);
1266             /* SubmoduleIdentNumber */
1267                 offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, 
1268                             hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
1269             /* SubmoduleProperties */
1270                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1271                             hf_pn_io_submodule_properties, &u16SubmoduleProperties);
1272
1273             switch(u16SubmoduleProperties & 0x03) {
1274             case(0x00): /* no input and no output data (one Input DataDescription Block follows) */
1275                 offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
1276                 break;
1277             case(0x01): /* input data (one Input DataDescription Block follows) */
1278                 offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
1279                 break;
1280             case(0x02): /* output data (one Output DataDescription Block follows) */
1281                 offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
1282                 break;
1283             case(0x03): /* input and output data (one Input and one Output DataDescription Block follows) */
1284                 offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
1285                 offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
1286                 break;
1287             }
1288
1289             proto_item_append_text(sub_item, ": Subslot: 0x%x, SubmoduleIdent: 0x%x SubmoduleProperties: 0x%x", 
1290                 u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleProperties);
1291                 proto_item_set_len(sub_item, offset - u32SubStart);
1292         }
1293
1294             proto_item_set_len(api_item, offset - u32ApiStart);
1295     }
1296
1297     return offset;
1298 }
1299
1300
1301 /* dissect the ModuleDiffBlock */
1302 static int
1303 dissect_ModuleDiffBlock(tvbuff_t *tvb, int offset,
1304         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1305 {
1306     guint16 u16NumberOfAPIs;
1307     guint32 u32Api;
1308     guint16 u16NumberOfModules;
1309     guint16 u16SlotNr;
1310     guint32 u32ModuleIdentNumber;
1311     guint16 u16ModuleState;
1312     guint16 u16NumberOfSubmodules;
1313     guint16 u16SubslotNr;
1314     guint32 u32SubmoduleIdentNumber;
1315     guint16 u16SubmoduleState;
1316     proto_item *api_item;
1317         proto_tree *api_tree;
1318         guint32 u32ApiStart;
1319     proto_item *module_item;
1320         proto_tree *module_tree;
1321         guint32 u32ModuleStart;
1322     proto_item *sub_item;
1323         proto_tree *sub_tree;
1324         guint32 u32SubStart;
1325
1326
1327     /* NumberOfAPIs */
1328         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, 
1329                         hf_pn_io_number_of_apis, &u16NumberOfAPIs);
1330     while(u16NumberOfAPIs--) {
1331         api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
1332             api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
1333         u32ApiStart = offset;
1334
1335         /* API */
1336             offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, 
1337                             hf_pn_io_api, &u32Api);
1338         /* NumberOfModules */
1339             offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, 
1340                             hf_pn_io_number_of_modules, &u16NumberOfModules);
1341
1342         proto_item_append_text(api_item, ": %u, NumberOfModules: %u", 
1343             u32Api, u16NumberOfModules);
1344
1345         while(u16NumberOfModules--) {
1346             module_item = proto_tree_add_item(api_tree, hf_pn_io_module_tree, tvb, offset, 0, FALSE);
1347                 module_tree = proto_item_add_subtree(module_item, ett_pn_io_module);
1348             u32ModuleStart = offset;
1349
1350             /* SlotNumber */
1351                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, 
1352                                 hf_pn_io_slot_nr, &u16SlotNr);
1353             /* ModuleIdentNumber */
1354                 offset = dissect_dcerpc_uint32(tvb, offset, pinfo, module_tree, drep, 
1355                                 hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
1356             /* ModuleState */
1357                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, 
1358                                 hf_pn_io_module_state, &u16ModuleState);
1359             /* NumberOfSubmodules */
1360                 offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, 
1361                                 hf_pn_io_number_of_submodules, &u16NumberOfSubmodules);
1362
1363             proto_item_append_text(module_item, ": Slot 0x%x, ModuleIdent: 0x%x ModuleState: %s NumberOfSubmodules: %u", 
1364                 u16SlotNr, u32ModuleIdentNumber, 
1365                 val_to_str(u16ModuleState, pn_io_module_state, "(0x%x)"), 
1366                 u16NumberOfSubmodules);
1367
1368             while(u16NumberOfSubmodules--) {
1369                 sub_item = proto_tree_add_item(module_tree, hf_pn_io_submodule_tree, tvb, offset, 0, FALSE);
1370                     sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule);
1371                 u32SubStart = offset;
1372
1373                 /* Subslotnumber */
1374                     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1375                                     hf_pn_io_subslot_nr, &u16SubslotNr);
1376                 /* SubmoduleIdentNumber */
1377                     offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, 
1378                                 hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
1379                 /* SubmoduleState */
1380                     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, 
1381                                 hf_pn_io_submodule_state, &u16SubmoduleState);
1382
1383                 proto_item_append_text(sub_item, ": Subslot 0x%x, SubmoduleIdentNumber: 0x%x, SubmoduleState: 0x%x", 
1384                     u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleState);
1385
1386                     proto_item_set_len(sub_item, offset - u32SubStart);
1387             } /* NumberOfSubmodules */
1388
1389                 proto_item_set_len(module_item, offset - u32ModuleStart);
1390         }
1391
1392             proto_item_set_len(api_item, offset - u32ApiStart);
1393     }
1394
1395     return offset;
1396 }
1397
1398
1399 /* dissect one PN-IO block (depending on the block type) */
1400 static int
1401 dissect_block(tvbuff_t *tvb, int offset,
1402         packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen)
1403 {
1404     guint16 u16BlockType;
1405     guint16 u16BlockLength;
1406     guint8 u8BlockVersionHigh;
1407     guint8 u8BlockVersionLow;
1408         proto_item *sub_item;
1409         proto_tree *sub_tree;
1410         guint32 u32SubStart;
1411     guint16 u16BodyLength;
1412         proto_item *header_item;
1413         proto_tree *header_tree;
1414
1415
1416     /* from here, we only have big endian (network byte ordering)!!! */
1417     drep[0] &= ~0x10;
1418
1419     sub_item = proto_tree_add_item(tree, hf_pn_io_block, tvb, offset, 0, FALSE);
1420         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_block);
1421     u32SubStart = offset;
1422
1423     header_item = proto_tree_add_item(sub_tree, hf_pn_io_block_header, tvb, offset, 6, FALSE);
1424         header_tree = proto_item_add_subtree(header_item, ett_pn_io_block_header);
1425
1426         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep, 
1427                         hf_pn_io_block_type, &u16BlockType);
1428         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep, 
1429                         hf_pn_io_block_length, &u16BlockLength);
1430         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep, 
1431                         hf_pn_io_block_version_high, &u8BlockVersionHigh);
1432         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep, 
1433                         hf_pn_io_block_version_low, &u8BlockVersionLow);
1434
1435     /* XXX - append block_header data to header_item */
1436
1437     /* block length is without type and length fields, but with version field */
1438     /* as it's already dissected, remove it */
1439     u16BodyLength = u16BlockLength - 2;
1440     tvb_ensure_bytes_exist(tvb, offset, u16BodyLength);
1441
1442     switch(u16BlockType) {
1443     case(0x0001):
1444     case(0x0002):
1445         dissect_Alarm_note_block(tvb, offset, pinfo, sub_tree, drep, u16BodyLength);
1446         break;
1447     case(0x0101):
1448         dissect_ARBlockReq(tvb, offset, pinfo, sub_tree, drep);
1449         break;
1450     case(0x0102):
1451         dissect_IOCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
1452         break;
1453     case(0x0103):
1454         dissect_AlarmCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
1455         break;
1456     case(0x0104):
1457         dissect_ExpectedSubmoduleBlockReq(tvb, offset, pinfo, sub_tree, drep);
1458         break;
1459     case(0x0106):
1460         dissect_MCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
1461         break;
1462     case(0x0110):
1463     case(0x0112):
1464     case(0x0114):
1465         if (check_col(pinfo->cinfo, COL_INFO))
1466                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1467             val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
1468         dissect_ControlConnect_block(tvb, offset, pinfo, sub_tree, drep);
1469         break;
1470     case(0x0008):
1471     case(0x0009):
1472         dissect_ReadWrite_rqst_block(tvb, offset, pinfo, sub_tree, drep, u16Index, u32RecDataLen);
1473         break;
1474     case(0x8001):
1475     case(0x8002):
1476         dissect_Alarm_ack_block(tvb, offset, pinfo, sub_tree, drep);
1477         break;
1478     case(0x8008):
1479     case(0x8009):
1480         dissect_ReadWrite_resp_block(tvb, offset, pinfo, sub_tree, drep, u16Index);
1481         break;
1482     case(0x8101):
1483         dissect_ARBlockRes(tvb, offset, pinfo, sub_tree, drep);
1484         break;
1485     case(0x8102):
1486         dissect_IOCRBlockRes(tvb, offset, pinfo, sub_tree, drep);
1487         break;
1488     case(0x8103):
1489         dissect_AlarmCRBlockRes(tvb, offset, pinfo, sub_tree, drep);
1490         break;
1491     case(0x8104):
1492         dissect_ModuleDiffBlock(tvb, offset, pinfo, sub_tree, drep);
1493         break;
1494     case(0x8110):
1495     case(0x8112):
1496     case(0x8114):
1497         if (check_col(pinfo->cinfo, COL_INFO))
1498                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1499             val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
1500         dissect_ControlConnect_block(tvb, offset, pinfo, sub_tree, drep);
1501         break;
1502     default:
1503         if (check_col(pinfo->cinfo, COL_INFO) && *u16Index < 3)
1504                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1505             val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
1506         proto_tree_add_string_format(sub_tree, hf_pn_io_data, tvb, offset, u16BodyLength, "undecoded", "Undecoded Data: %d bytes", u16BodyLength);
1507     }
1508     offset += u16BodyLength;
1509
1510         proto_item_append_text(sub_item, "[%u]: Type=\"%s\" (0x%04x), Length=%u(+4), Version=%u.%u", 
1511                 *u16Index, val_to_str(u16BlockType, pn_io_block_type, "Unknown"), u16BlockType,
1512         u16BlockLength, u8BlockVersionHigh, u8BlockVersionLow);
1513         proto_item_set_len(sub_item, offset - u32SubStart);
1514
1515     return offset;
1516 }
1517
1518
1519 /* dissect any number of PN-IO blocks */
1520 static int
1521 dissect_blocks(tvbuff_t *tvb, int offset,
1522         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1523 {
1524     guint16 u16Index = 0;
1525     guint32 u32RecDataLen;
1526     
1527
1528     while(tvb_length(tvb) > (guint) offset) {
1529         offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
1530         u16Index++;
1531     }
1532
1533     /* we don't want to have too many blocks in the info column */
1534     if(u16Index > 3) {
1535         if (check_col(pinfo->cinfo, COL_INFO))
1536                 col_append_fstr(pinfo->cinfo, COL_INFO, ", ... (%u blocks)",
1537             u16Index);
1538     }
1539         return offset;
1540 }
1541
1542
1543 /* dissect a PN-IO (DCE-RPC) request header */
1544 static int
1545 dissect_IPNIO_rqst_header(tvbuff_t *tvb, int offset,
1546         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1547 {
1548     guint32 u32ArgsMax;
1549     guint32 u32ArgsLen;
1550     guint32 u32MaxCount;
1551     guint32 u32Offset;
1552     guint32 u32ArraySize;
1553
1554         proto_item *sub_item;
1555         proto_tree *sub_tree;
1556         guint32 u32SubStart;
1557
1558
1559         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1560             col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM");
1561
1562     /* args_max */
1563         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, 
1564                         hf_pn_io_args_max, &u32ArgsMax);
1565     /* args_len */
1566         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, 
1567                         hf_pn_io_args_len, &u32ArgsLen);
1568
1569     sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, FALSE);
1570         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io);
1571     u32SubStart = offset;
1572
1573     /* RPC array header */
1574         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1575                         hf_pn_io_array_max_count, &u32MaxCount);
1576         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1577                         hf_pn_io_array_offset, &u32Offset);
1578         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1579                         hf_pn_io_array_act_count, &u32ArraySize);
1580
1581         proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u", 
1582         u32MaxCount, u32Offset, u32ArraySize);
1583         proto_item_set_len(sub_item, offset - u32SubStart);
1584
1585     return offset;
1586 }
1587
1588
1589 /* dissect a PN-IO (DCE-RPC) response header */
1590 static int
1591 dissect_IPNIO_resp_header(tvbuff_t *tvb, int offset,
1592         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1593 {
1594     guint32 u32ArgsLen;
1595     guint32 u32MaxCount;
1596     guint32 u32Offset;
1597     guint32 u32ArraySize;
1598
1599         proto_item *sub_item;
1600         proto_tree *sub_tree;
1601         guint32 u32SubStart;
1602
1603
1604         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1605             col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM");
1606
1607     offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
1608
1609     /* args_len */
1610         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, 
1611                         hf_pn_io_args_len, &u32ArgsLen);
1612
1613     sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, FALSE);
1614         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io);
1615     u32SubStart = offset;
1616
1617     /* RPC array header */
1618         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1619                         hf_pn_io_array_max_count, &u32MaxCount);
1620         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1621                         hf_pn_io_array_offset, &u32Offset);
1622         offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep, 
1623                         hf_pn_io_array_act_count, &u32ArraySize);
1624
1625     proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u", 
1626         u32MaxCount, u32Offset, u32ArraySize);
1627         proto_item_set_len(sub_item, offset - u32SubStart);
1628
1629     return offset;
1630 }
1631
1632
1633 /* dissect a PN-IO connect request */
1634 static int
1635 dissect_IPNIO_Connect_rqst(tvbuff_t *tvb, int offset,
1636         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1637 {
1638     
1639     offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
1640
1641     /* IODConnectReq */
1642     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1643
1644         return offset;
1645 }
1646
1647
1648 /* dissect a PN-IO connect response */
1649 static int
1650 dissect_IPNIO_Connect_resp(tvbuff_t *tvb, int offset,
1651         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1652 {
1653
1654     offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
1655
1656     /* IODConnectRes */
1657     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1658
1659         return offset;
1660 }
1661
1662
1663 /* dissect a PN-IO release request */
1664 static int
1665 dissect_IPNIO_Release_rqst(tvbuff_t *tvb, int offset,
1666         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1667 {
1668     
1669     offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
1670
1671     /* IODReleaseReq */
1672     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1673
1674         return offset;
1675 }
1676
1677
1678 /* dissect a PN-IO release response */
1679 static int
1680 dissect_IPNIO_Release_resp(tvbuff_t *tvb, int offset,
1681         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1682 {
1683
1684     offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
1685
1686     /* IODReleaseRes */
1687     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1688
1689         return offset;
1690 }
1691
1692
1693 /* dissect a PN-IO control request */
1694 static int
1695 dissect_IPNIO_Control_rqst(tvbuff_t *tvb, int offset,
1696         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1697 {
1698     
1699     offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
1700
1701     /* IODControlReq */
1702     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1703
1704     return offset;
1705 }
1706
1707
1708 /* dissect a PN-IO control response */
1709 static int
1710 dissect_IPNIO_Control_resp(tvbuff_t *tvb, int offset,
1711         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1712 {
1713
1714     offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
1715
1716     /* IODControlRes */
1717     offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
1718
1719     return offset;
1720 }
1721
1722
1723 /* dissect a PN-IO read request */
1724 static int
1725 dissect_IPNIO_Read_rqst(tvbuff_t *tvb, int offset,
1726         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1727 {
1728     guint16 u16Index = 0;
1729     guint32 u32RecDataLen;
1730
1731     offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
1732
1733     /* IODReadReq */
1734     offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
1735
1736         return offset;
1737 }
1738
1739
1740 /* dissect a PN-IO read response */
1741 static int
1742 dissect_IPNIO_Read_resp(tvbuff_t *tvb, int offset,
1743         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1744 {
1745     gint remain;
1746     guint16 u16Index = 0;
1747     guint32 u32RecDataLen;
1748
1749     offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
1750
1751     /* IODReadHeader */
1752     offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
1753
1754     /* XXX - RecordDataRead: dissection not yet implemented */
1755     remain = tvb_length_remaining(tvb, offset);
1756     proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, remain, "data", "User Data: %d bytes", remain);
1757     offset += remain;
1758
1759         return offset;
1760 }
1761
1762
1763 static int
1764 dissect_IODWriteReq(tvbuff_t *tvb, int offset,
1765         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1766 {
1767     gint remain;
1768     guint16 u16Index = 0;
1769     guint32 u32RecDataLen;
1770
1771
1772     /* IODWriteHeader */
1773     offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
1774
1775
1776     /* IODWriteMultipleReq? */
1777     if(u16Index == 0xe040) {
1778         while((remain = tvb_length_remaining(tvb, offset)) > 0) {
1779             offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep);
1780         }
1781     } else {
1782         /* RecordDataWrite */
1783         /* XXX - dissection not yet implemented */
1784         proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, u32RecDataLen, "data", "RecordDataWrite: %d bytes", u32RecDataLen);
1785         offset += u32RecDataLen;
1786
1787         /* XXX - add padding (required with IODWriteMultipleReq) */
1788         switch(offset % 4) {
1789         case(3):
1790             offset += 1;
1791             break;
1792         case(2):
1793             offset += 2;
1794             break;
1795         case(1):
1796             offset += 3;
1797             break;
1798         }
1799     }
1800
1801     return offset;
1802 }
1803
1804 /* dissect a PN-IO write request */
1805 static int
1806 dissect_IPNIO_Write_rqst(tvbuff_t *tvb, int offset,
1807         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1808 {
1809     offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
1810
1811     offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep);
1812
1813         return offset;
1814 }
1815
1816
1817
1818 static int
1819 dissect_IODWriteRes(tvbuff_t *tvb, int offset,
1820         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1821 {
1822     gint remain;
1823     guint16 u16Index = 0;
1824     guint32 u32RecDataLen;
1825
1826
1827     /* IODWriteResHeader */
1828     offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
1829
1830     /* IODWriteMultipleRes? */
1831     if(u16Index == 0xe040) {
1832         while((remain = tvb_length_remaining(tvb, offset)) > 0) {
1833             offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
1834         }
1835     }
1836
1837     return offset;
1838 }
1839
1840
1841 /* dissect a PN-IO write response */
1842 static int
1843 dissect_IPNIO_Write_resp(tvbuff_t *tvb, int offset,
1844         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1845 {
1846     guint16 u16Index = 0;
1847
1848     offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
1849
1850     offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
1851
1852         return offset;
1853 }
1854
1855
1856 /* dissect the IOxS (IOCS, IOPS) field */
1857 static int
1858 dissect_PNIO_IOxS(tvbuff_t *tvb, int offset,
1859         packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_)
1860 {
1861     guint8 u8IOxS;
1862     proto_item *ioxs_item = NULL;
1863     proto_tree *ioxs_tree = NULL;
1864
1865
1866     u8IOxS = tvb_get_guint8(tvb, offset);
1867
1868     /* add ioxs subtree */
1869         ioxs_item = proto_tree_add_uint_format(tree, hf_pn_io_ioxs, 
1870                 tvb, offset, 1, u8IOxS,
1871                 "IOxS: 0x%02x (%s%s)", 
1872                 u8IOxS, 
1873                 (u8IOxS & 0x01) ? "another IOxS follows " : "",
1874                 (u8IOxS & 0x80) ? "good" : "bad");
1875         ioxs_tree = proto_item_add_subtree(ioxs_item, ett_pn_io_ioxs);
1876
1877         proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_extension, tvb, offset, 1, u8IOxS);
1878         proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_res14, tvb, offset, 1, u8IOxS);
1879         proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_instance, tvb, offset, 1, u8IOxS);
1880         proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_datastate, tvb, offset, 1, u8IOxS);
1881
1882     return offset + 1;
1883 }
1884
1885
1886 /* dissect a PN-IO Cyclic Service Data Unit (on top of PN-RT protocol) */
1887 static int
1888 dissect_PNIO_C_SDU(tvbuff_t *tvb, int offset,
1889         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1890 {
1891     proto_item *data_item;
1892         proto_tree *data_tree;
1893
1894
1895     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1896             col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO");
1897
1898     if(tree) {
1899             data_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_length(tvb),
1900                                     "PROFINET IO Cyclic Service Data Unit: %u bytes", tvb_length(tvb));
1901         data_tree = proto_item_add_subtree(data_item, ett_pn_io_rtc);
1902
1903         offset = dissect_PNIO_IOxS(tvb, offset, pinfo, data_tree, drep);
1904
1905         /* XXX - dissect the remaining data */
1906         /* this will be one or more DataItems followed by an optional GAP and RTCPadding */
1907         /* as we don't have the required context information to dissect the specific DataItems, this will be tricky :-( */
1908             data_item = proto_tree_add_protocol_format(data_tree, proto_pn_io, tvb, offset, tvb_length_remaining(tvb, offset),
1909                                     "Data: %u bytes (including GAP and RTCPadding)", tvb_length_remaining(tvb, offset));
1910     }
1911
1912     return offset;
1913 }
1914
1915
1916 /* dissect a PN-IO RTA PDU (on top of PN-RT protocol) */
1917 static int
1918 dissect_PNIO_RTA(tvbuff_t *tvb, int offset,
1919         packet_info *pinfo, proto_tree *tree, guint8 *drep)
1920 {
1921     guint16 u16AlarmDstEndpoint;
1922     guint16 u16AlarmSrcEndpoint;
1923     guint8  u8PDUType;
1924     guint8  u8PDUVersion;
1925     guint8  u8WindowSize;
1926     guint8  u8Tack;
1927     guint16 u16SendSeqNum;
1928     guint16 u16AckSeqNum;
1929     guint16 u16VarPartLen;
1930     int     start_offset = offset;
1931     guint16 u16Index = 0;
1932     guint32 u32RecDataLen;
1933
1934
1935     proto_item *rta_item;
1936         proto_tree *rta_tree;
1937
1938     proto_item *sub_item;
1939         proto_tree *sub_tree;
1940
1941
1942         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1943             col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-AL");
1944
1945         rta_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_length(tvb), 
1946         "PROFINET IO Alarm");
1947         rta_tree = proto_item_add_subtree(rta_item, ett_pn_io_rta);
1948
1949     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, 
1950                     hf_pn_io_alarm_dst_endpoint, &u16AlarmDstEndpoint);
1951     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, 
1952                     hf_pn_io_alarm_src_endpoint, &u16AlarmSrcEndpoint);
1953
1954     if (check_col(pinfo->cinfo, COL_INFO))
1955             col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: 0x%x, Dst: 0x%x",
1956         u16AlarmSrcEndpoint, u16AlarmDstEndpoint);
1957
1958     /* PDU type */
1959         sub_item = proto_tree_add_item(rta_tree, hf_pn_io_pdu_type, tvb, offset, 1, FALSE);
1960         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type);
1961     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1962                     hf_pn_io_pdu_type_type, &u8PDUType);
1963     u8PDUType &= 0x0F;
1964     offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1965                     hf_pn_io_pdu_type_version, &u8PDUVersion);
1966     u8PDUVersion >>= 4;
1967     proto_item_append_text(sub_item, ", Type: %s, Version: %u", 
1968         val_to_str(u8PDUType, pn_io_pdu_type, "Unknown"),
1969         u8PDUVersion);
1970
1971     /* additional flags */
1972         sub_item = proto_tree_add_item(rta_tree, hf_pn_io_add_flags, tvb, offset, 1, FALSE);
1973         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_add_flags);
1974     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1975                     hf_pn_io_window_size, &u8WindowSize);
1976     u8WindowSize &= 0x0F;
1977     offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, 
1978                     hf_pn_io_tack, &u8Tack);
1979     u8Tack >>= 4;
1980     proto_item_append_text(sub_item, ", Window Size: %u, Tack: %u", 
1981         u8WindowSize, u8Tack);
1982
1983     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, 
1984                     hf_pn_io_send_seq_num, &u16SendSeqNum);
1985     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, 
1986                     hf_pn_io_ack_seq_num, &u16AckSeqNum);
1987     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, 
1988                     hf_pn_io_var_part_len, &u16VarPartLen);
1989
1990     switch(u8PDUType & 0x0F) {
1991     case(1):    /* Data-RTA */
1992         if (check_col(pinfo->cinfo, COL_INFO))
1993                 col_append_str(pinfo->cinfo, COL_INFO, ", Data-RTA");
1994         offset = dissect_block(tvb, offset, pinfo, rta_tree, drep, &u16Index, &u32RecDataLen);
1995         break;
1996     case(2):    /* NACK-RTA */
1997         if (check_col(pinfo->cinfo, COL_INFO))
1998                 col_append_str(pinfo->cinfo, COL_INFO, ", NACK-RTA");
1999         /* no additional data */
2000         break;
2001     case(3):    /* ACK-RTA */
2002         if (check_col(pinfo->cinfo, COL_INFO))
2003                 col_append_str(pinfo->cinfo, COL_INFO, ", ACK-RTA");
2004         /* no additional data */
2005         break;
2006     case(4):    /* ERR-RTA */
2007         if (check_col(pinfo->cinfo, COL_INFO))
2008                 col_append_str(pinfo->cinfo, COL_INFO, ", ERR-RTA");
2009         offset = dissect_PNIO_status(tvb, offset, pinfo, rta_tree, drep);
2010         break;
2011     default:
2012         proto_tree_add_string_format(tree, hf_pn_io_data, tvb, 0, tvb_length(tvb), "data", 
2013             "PN-IO Alarm: unknown PDU type 0x%x", u8PDUType);    
2014     }
2015
2016     proto_item_set_len(rta_item, offset - start_offset);
2017
2018     return offset;
2019 }
2020
2021
2022 /* possibly dissect a PN-IO related PN-RT packet */
2023 static gboolean
2024 dissect_PNIO_heur(tvbuff_t *tvb, 
2025         packet_info *pinfo, proto_tree *tree)
2026 {
2027     guint8  drep_data = 0;
2028     guint8  *drep = &drep_data;
2029         guint8  u8CBAVersion;
2030     guint16 u16FrameID;
2031
2032
2033     /* the sub tvb will NOT contain the frame_id here! */
2034     u16FrameID = GPOINTER_TO_UINT(pinfo->private_data);
2035
2036     u8CBAVersion = tvb_get_guint8 (tvb, 0);
2037
2038     /* is this a PNIO class 2 data packet? */
2039         /* frame id must be in valid range (cyclic Real-Time, class=2) */
2040         if (u16FrameID >= 0x8000 && u16FrameID < 0xbf00) {
2041         dissect_PNIO_C_SDU(tvb, 0, pinfo, tree, drep);
2042         return TRUE;
2043     }
2044
2045     /* is this a PNIO class 1 data packet? */
2046         /* frame id must be in valid range (cyclic Real-Time, class=1) and
2047      * first byte (CBA version field) has to be != 0x11 */
2048         if (u16FrameID >= 0xc000 && u16FrameID < 0xfb00 && u8CBAVersion != 0x11) {
2049         dissect_PNIO_C_SDU(tvb, 0, pinfo, tree, drep);
2050         return TRUE;
2051     }
2052
2053     /* is this a PNIO high priority alarm packet? */
2054     if(u16FrameID == 0xfc01) {
2055         if (check_col(pinfo->cinfo, COL_INFO))
2056                 col_add_str(pinfo->cinfo, COL_INFO, "Alarm High");
2057
2058         dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep);
2059         return TRUE;
2060     }
2061
2062     /* is this a PNIO low priority alarm packet? */
2063     if(u16FrameID == 0xfe01) {
2064         if (check_col(pinfo->cinfo, COL_INFO))
2065                 col_add_str(pinfo->cinfo, COL_INFO, "Alarm Low");
2066
2067         dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep);
2068         return TRUE;
2069     }
2070
2071     /* this PN-RT packet doesn't seem to be PNIO specific */
2072     return FALSE;
2073 }
2074
2075
2076 /* the PNIO dcerpc interface table */
2077 static dcerpc_sub_dissector pn_io_dissectors[] = {
2078 { 0, "Connect", dissect_IPNIO_Connect_rqst, dissect_IPNIO_Connect_resp },
2079 { 1, "Release", dissect_IPNIO_Release_rqst, dissect_IPNIO_Release_resp },
2080 { 2, "Read",    dissect_IPNIO_Read_rqst,    dissect_IPNIO_Read_resp },
2081 { 3, "Write",   dissect_IPNIO_Write_rqst,   dissect_IPNIO_Write_resp },
2082 { 4, "Control", dissect_IPNIO_Control_rqst, dissect_IPNIO_Control_resp },
2083         { 0, NULL, NULL, NULL }
2084 };
2085
2086
2087 void
2088 proto_register_pn_io (void)
2089 {
2090         static hf_register_info hf[] = {
2091         { &hf_pn_io_opnum,
2092                 { "Operation", "pn_io.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2093         { &hf_pn_io_reserved16,
2094                 { "Reserved", "pn_io.reserved16", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2095         { &hf_pn_io_array,
2096         { "Array", "pn_io.array", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2097         { &hf_pn_io_status,
2098                 { "Status", "pn_io.status", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2099         { &hf_pn_io_args_max,
2100                 { "ArgsMaximum", "pn_io.args_max", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2101         { &hf_pn_io_args_len,
2102                 { "ArgsLength", "pn_io.args_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2103         { &hf_pn_io_array_max_count,
2104                 { "MaximumCount", "pn_io.array_max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2105         { &hf_pn_io_array_offset,
2106                 { "Offset", "pn_io.array_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2107         { &hf_pn_io_array_act_count,
2108                 { "ActualCount", "pn_io.array_act_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2109
2110     { &hf_pn_io_ar_type,
2111     { "ARType", "pn_io.ar_type", FT_UINT16, BASE_HEX, VALS(pn_io_ar_type), 0x0, "", HFILL }},
2112         { &hf_pn_io_cminitiator_macadd,
2113       { "CMInitiatorMacAdd", "pn_io.cminitiator_mac_add", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
2114         { &hf_pn_io_cminitiator_objectuuid,
2115       { "CMInitiatorObjectUUID", "pn_io.cminitiator_uuid", FT_STRING, BASE_DEC, 0x0, 0x0, "", HFILL }},
2116         { &hf_pn_io_ar_properties,
2117                 { "ARProperties", "pn_io.ar_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - 32 bitfield! */
2118         { &hf_pn_io_cminitiator_activitytimeoutfactor,
2119                 { "CMInitiatorActivityTimeoutFactor", "pn_io.cminitiator_activitytimeoutfactor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},  /* XXX - special values */
2120         { &hf_pn_io_cminitiator_udprtport,
2121                 { "CMInitiatorUDPRTPort", "pn_io.cminitiator_udprtport", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - special values */
2122         { &hf_pn_io_station_name_length,
2123                 { "StationNameLength", "pn_io.station_name_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2124         { &hf_pn_io_cminitiator_station_name,
2125                 { "CMInitiatorStationName", "pn_io.cminitiator_station_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
2126
2127         { &hf_pn_io_cmresponder_macadd,
2128       { "CMResponderMacAdd", "pn_io.cmresponder_macadd", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
2129         { &hf_pn_io_cmresponder_udprtport,
2130                 { "CMResponderUDPRTPort", "pn_io.cmresponder_udprtport", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - special values */
2131
2132     { &hf_pn_io_iocr_type,
2133     { "IOCRType", "pn_io.iocr_type", FT_UINT16, BASE_HEX, VALS(pn_io_iocr_type), 0x0, "", HFILL }},
2134     { &hf_pn_io_iocr_reference,
2135     { "IOCRReference", "pn_io.iocr_reference", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2136     { &hf_pn_io_lt,
2137     { "LT", "pn_io.lt", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2138         { &hf_pn_io_iocr_properties,
2139     { "IOCRProperties", "pn_io.iocr_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - 32 bitfield! */
2140     { &hf_pn_io_data_length,
2141       { "DataLength", "pn_io.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2142     { &hf_pn_io_frame_id,
2143       { "FrameID", "pn_io.frame_id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2144     { &hf_pn_io_send_clock_factor,
2145       { "SendClockFactor", "pn_io.send_clock_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
2146     { &hf_pn_io_reduction_ratio,
2147       { "ReductionRatio", "pn_io.reduction_ratio", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
2148     { &hf_pn_io_phase,
2149       { "Phase", "pn_io.phase", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2150     { &hf_pn_io_sequence,
2151       { "Sequence", "pn_io.sequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2152     { &hf_pn_io_frame_send_offset,
2153       { "FrameSendOffset", "pn_io.frame_send_offset", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
2154     { &hf_pn_io_watchdog_factor,
2155       { "WatchdogFactor", "pn_io.watchdog_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2156     { &hf_pn_io_data_hold_factor,
2157       { "DataHoldFactor", "pn_io.data_hold_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2158     { &hf_pn_io_iocr_tag_header,
2159       { "IOCRTagHeader", "pn_io.iocr_tag_header", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2160     { &hf_pn_io_iocr_multicast_mac_add,
2161       { "IOCRMulticastMACAdd", "pn_io.iocr_multicast_mac_add", FT_ETHER, BASE_HEX, NULL, 0x0, "", HFILL }},
2162     { &hf_pn_io_number_of_apis,
2163       { "NumberOfAPIs", "pn_io.number_of_apis", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2164     { &hf_pn_io_number_of_io_data_objects,
2165       { "NumberOfIODataObjects", "pn_io.number_of_io_data_objects", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2166     { &hf_pn_io_io_data_object_frame_offset,
2167       { "IODataObjectFrameOffset", "pn_io.io_data_object_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2168     { &hf_pn_io_number_of_iocs,
2169       { "NumberOfIOCS", "pn_io.number_of_iocs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2170     { &hf_pn_io_iocs_frame_offset,
2171       { "IOCSFrameOffset", "pn_io.iocs_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2172
2173     { &hf_pn_io_alarmcr_type,
2174     { "AlarmCRType", "pn_io.alarmcr_type", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2175         { &hf_pn_io_alarmcr_properties,
2176     { "AlarmCRProperties", "pn_io.alarmcr_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - 32 bitfield! */
2177         { &hf_pn_io_rta_timeoutfactor,
2178                 { "RTATimeoutFactor", "pn_io.rta_timeoutfactor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},  /* XXX - special values */
2179         { &hf_pn_io_rta_retries,
2180                 { "RTARetries", "pn_io.rta_retries", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},  /* XXX - only values 3 - 15 allowed */
2181         { &hf_pn_io_localalarmref,
2182                 { "LocalAlarmReference", "pn_io.localalarmref", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - special values */
2183         { &hf_pn_io_maxalarmdatalength,
2184                 { "MaxAlarmDataLength", "pn_io.maxalarmdatalength", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},  /* XXX - only values 200 - 1432 allowed */
2185         { &hf_pn_io_alarmcr_tagheaderhigh,
2186                 { "AlarmCRTagHeaderHigh", "pn_io.alarmcr_tagheaderhigh", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - 16 bitfield! */
2187         { &hf_pn_io_alarmcr_tagheaderlow,
2188                 { "AlarmCRTagHeaderLow", "pn_io.alarmcr_tagheaderlow", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},  /* XXX - 16 bitfield!*/
2189
2190     { &hf_pn_io_api_tree,
2191       { "API", "pn_io.api", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2192     { &hf_pn_io_module_tree,
2193       { "Module", "pn_io.module", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2194     { &hf_pn_io_submodule_tree,
2195       { "Submodule", "pn_io.submodule", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2196     { &hf_pn_io_io_data_object,
2197       { "IODataObject", "pn_io.io_data_object", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2198     { &hf_pn_io_io_cs,
2199       { "IOCS", "pn_io.io_cs", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2200
2201     { &hf_pn_io_ar_uuid,
2202       { "ARUUID", "pn_io.ar_uuid", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
2203     { &hf_pn_io_api,
2204       { "API", "pn_io.api", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
2205     { &hf_pn_io_slot_nr,
2206       { "SlotNumber", "pn_io.slot_nr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2207     { &hf_pn_io_subslot_nr,
2208       { "SubslotNumber", "pn_io.subslot_nr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2209     { &hf_pn_io_index,
2210       { "Index", "pn_io.index", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2211     { &hf_pn_io_seq_number,
2212       { "SeqNumber", "pn_io.seq_number", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2213     { &hf_pn_io_record_data_length,
2214       { "RecordDataLength", "pn_io.record_data_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
2215     { &hf_pn_io_padding,
2216       { "Padding", "pn_io.padding", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
2217     { &hf_pn_io_add_val1,
2218       { "AdditionalValue1", "pn_io.add_val1", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2219     { &hf_pn_io_add_val2,
2220       { "AdditionalValue2", "pn_io.add_val2", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2221     { &hf_pn_io_block_header,
2222       { "BlockHeader", "pn_io.block_header", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2223     { &hf_pn_io_block_type,
2224       { "BlockType", "pn_io.block_type", FT_UINT16, BASE_HEX, VALS(pn_io_block_type), 0x0, "", HFILL }},
2225     { &hf_pn_io_block_length,
2226       { "BlockLength", "pn_io.block_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2227     { &hf_pn_io_block_version_high,
2228       { "BlockVersionHigh", "pn_io.block_version_high", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2229     { &hf_pn_io_block_version_low,
2230       { "BlockVersionLow", "pn_io.block_version_low", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2231     { &hf_pn_io_sessionkey,
2232       { "SessionKey", "pn_io.session_key", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2233     { &hf_pn_io_control_command,
2234       { "ControlCommand", "pn_io.control_command", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2235     { &hf_pn_io_control_command_prmend,
2236       { "PrmEnd", "pn_io.control_command.prmend", FT_UINT16, BASE_DEC, NULL, 0x0001, "", HFILL }},
2237     { &hf_pn_io_control_command_applready,
2238       { "ApplicationReady", "pn_io.control_command.applready", FT_UINT16, BASE_DEC, NULL, 0x0002, "", HFILL }},
2239     { &hf_pn_io_control_command_release,
2240       { "Release", "pn_io.control_command.release", FT_UINT16, BASE_DEC, NULL, 0x0004, "", HFILL }},
2241     { &hf_pn_io_control_command_done,
2242       { "Done", "pn_io.control_command.done", FT_UINT16, BASE_DEC, NULL, 0x0008, "", HFILL }},
2243     { &hf_pn_io_control_block_properties,
2244       { "ControlBlockProperties", "pn_io.control_block_properties", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2245
2246     { &hf_pn_io_error_code,
2247       { "ErrorCode", "pn_io.error_code", FT_UINT8, BASE_HEX, VALS(pn_io_error_code), 0x0, "", HFILL }},
2248     { &hf_pn_io_error_decode,
2249       { "ErrorDecode", "pn_io.error_decode", FT_UINT8, BASE_HEX, VALS(pn_io_error_decode), 0x0, "", HFILL }},
2250     { &hf_pn_io_error_code1,
2251       { "ErrorCode1", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1), 0x0, "", HFILL }},
2252     { &hf_pn_io_error_code2,
2253       { "ErrorCode2", "pn_io.error_code2", FT_UINT8, BASE_HEX, VALS(pn_io_error_code2), 0x0, "", HFILL }},
2254     { &hf_pn_io_error_code1_pniorw,
2255       { "ErrorCode1 (PNIORW)", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1_pniorw), 0x0, "", HFILL }},
2256     { &hf_pn_io_error_code1_pnio,
2257       { "ErrorCode1 (PNIO)", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1_pnio), 0x0, "", HFILL }},
2258         { &hf_pn_io_block,
2259     { "Block", "pn_io.block", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2260     { &hf_pn_io_data,
2261       { "Undecoded Data", "pn_io.data", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
2262
2263     { &hf_pn_io_alarm_type,
2264       { "AlarmType", "pn_io.alarm_type", FT_UINT16, BASE_HEX, VALS(pn_io_alarm_type), 0x0, "", HFILL }},
2265
2266     { &hf_pn_io_alarm_specifier,
2267       { "AlarmSpecifier", "pn_io.alarm_specifier", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2268     { &hf_pn_io_alarm_specifier_sequence,
2269       { "SequenceNumber", "pn_io.alarm_specifier.sequence", FT_UINT16, BASE_HEX, NULL, 0x07FF, "", HFILL }},
2270     { &hf_pn_io_alarm_specifier_channel,
2271       { "ChannelDiagnosis", "pn_io.alarm_specifier.channel", FT_UINT16, BASE_HEX, NULL, 0x0800, "", HFILL }},
2272     { &hf_pn_io_alarm_specifier_manufacturer,
2273       { "ManufacturerSpecificDiagnosis", "pn_io.alarm_specifier.manufacturer", FT_UINT16, BASE_HEX, NULL, 0x1000, "", HFILL }},
2274     { &hf_pn_io_alarm_specifier_submodule,
2275       { "SubmoduleDiagnosisState", "pn_io.alarm_specifier.submodule", FT_UINT16, BASE_HEX, NULL, 0x2000, "", HFILL }},
2276     { &hf_pn_io_alarm_specifier_ardiagnosis,
2277       { "ARDiagnosisState", "pn_io.alarm_specifier.ardiagnosis", FT_UINT16, BASE_HEX, NULL, 0x8000, "", HFILL }},
2278
2279     { &hf_pn_io_alarm_dst_endpoint,
2280       { "AlarmDstEndpoint", "pn_io.alarm_dst_endpoint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2281     { &hf_pn_io_alarm_src_endpoint,
2282       { "AlarmSrcEndpoint", "pn_io.alarm_src_endpoint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2283     { &hf_pn_io_pdu_type,
2284       { "PDUType", "pn_io.pdu_type", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2285     { &hf_pn_io_pdu_type_type,
2286       { "Type", "pn_io.pdu_type.type", FT_UINT8, BASE_HEX, VALS(pn_io_pdu_type), 0x0F, "", HFILL }},
2287     { &hf_pn_io_pdu_type_version,
2288       { "Version", "pn_io.pdu_type.version", FT_UINT8, BASE_HEX, NULL, 0xF0, "", HFILL }},
2289     { &hf_pn_io_add_flags,
2290       { "AddFlags", "pn_io.add_flags", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2291     { &hf_pn_io_window_size,
2292       { "WindowSize", "pn_io.window_size", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }},
2293     { &hf_pn_io_tack,
2294       { "TACK", "pn_io.tack", FT_UINT8, BASE_HEX, NULL, 0xF0, "", HFILL }},
2295     { &hf_pn_io_send_seq_num,
2296       { "SendSeqNum", "pn_io.send_seq_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2297     { &hf_pn_io_ack_seq_num,
2298       { "AckSeqNum", "pn_io.ack_seq_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2299     { &hf_pn_io_var_part_len,
2300       { "VarPartLen", "pn_io.var_part_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2301     { &hf_pn_io_module_ident_number,
2302       { "ModuleIdentNumber", "pn_io.module_ident_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
2303     { &hf_pn_io_submodule_ident_number,
2304       { "SubmoduleIdentNumber", "pn_io.submodule_ident_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
2305
2306     { &hf_pn_io_number_of_modules,
2307       { "NumberOfModules", "pn_io.number_of_modules", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2308     { &hf_pn_io_module_properties,
2309       { "ModuleProperties", "pn_io.module_properties", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2310     { &hf_pn_io_module_state,
2311       { "ModuleState", "pn_io.module_state", FT_UINT16, BASE_HEX, VALS(pn_io_module_state), 0x0, "", HFILL }},
2312     { &hf_pn_io_number_of_submodules,
2313       { "NumberOfSubmodules", "pn_io.number_of_submodules", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2314     { &hf_pn_io_submodule_properties,
2315       { "SubmoduleProperties", "pn_io.submodule_properties", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2316     { &hf_pn_io_submodule_state,
2317       { "SubmoduleState", "pn_io.submodule_state", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2318
2319     { &hf_pn_io_data_description_tree,
2320       { "DataDescription", "pn_io.data_description", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
2321     { &hf_pn_io_data_description,
2322       { "DataDescription", "pn_io.data_description", FT_UINT16, BASE_HEX, VALS(pn_io_data_description), 0x0, "", HFILL }},
2323     { &hf_pn_io_submodule_data_length,
2324       { "SubmoduleDataLength", "pn_io.submodule_data_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2325     { &hf_pn_io_length_iocs,
2326       { "LengthIOCS", "pn_io.length_iocs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2327     { &hf_pn_io_length_iops,
2328       { "LengthIOPS", "pn_io.length_iops", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2329
2330     { &hf_pn_io_ioxs,
2331       { "IOxS", "pn_io.ioxs", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
2332     { &hf_pn_io_ioxs_extension,
2333       { "Extension (1:another IOxS follows/0:no IOxS follows)", "pn_io.ioxs.extension", FT_UINT8, BASE_HEX, NULL, 0x01, "", HFILL }},
2334     { &hf_pn_io_ioxs_res14,
2335       { "Reserved (should be zero)", "pn_io.ioxs.res14", FT_UINT8, BASE_HEX, NULL, 0x1E, "", HFILL }},
2336     { &hf_pn_io_ioxs_instance,
2337       { "Instance (only valid, if DataState is bad)", "pn_io.ioxs.instance", FT_UINT8, BASE_HEX, VALS(pn_io_ioxs), 0x60, "", HFILL }},
2338     { &hf_pn_io_ioxs_datastate,
2339       { "DataState (1:good/0:bad)", "pn_io.ioxs.datastate", FT_UINT8, BASE_HEX, NULL, 0x80, "", HFILL }},
2340
2341     { &hf_pn_io_address_resolution_properties,
2342       { "AddressResolutionProperties", "pn_io.address_resolution_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
2343     { &hf_pn_io_mci_timeout_factor,
2344       { "MCITimeoutFactor", "pn_io.mci_timeout_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2345         { &hf_pn_io_provider_station_name,
2346                 { "ProviderStationName", "pn_io.provider_station_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}
2347
2348     };
2349
2350         static gint *ett[] = {
2351                 &ett_pn_io,
2352         &ett_pn_io_block,
2353         &ett_pn_io_block_header,
2354         &ett_pn_io_status,
2355         &ett_pn_io_rtc,
2356         &ett_pn_io_rta,
2357                 &ett_pn_io_pdu_type,
2358         &ett_pn_io_add_flags,
2359         &ett_pn_io_control_command,
2360         &ett_pn_io_ioxs,
2361         &ett_pn_io_api,
2362         &ett_pn_io_data_description,
2363         &ett_pn_io_module,
2364         &ett_pn_io_submodule,
2365         &ett_pn_io_io_data_object,
2366         &ett_pn_io_io_cs
2367         };
2368
2369         proto_pn_io = proto_register_protocol ("PROFINET IO", "PNIO", "pn_io");
2370         proto_register_field_array (proto_pn_io, hf, array_length (hf));
2371         proto_register_subtree_array (ett, array_length (ett));
2372 }
2373
2374 void
2375 proto_reg_handoff_pn_io (void)
2376 {
2377         /* Register the protocols as dcerpc */
2378         dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_device, ver_pn_io_device, pn_io_dissectors, hf_pn_io_opnum);
2379         dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_controller, ver_pn_io_controller, pn_io_dissectors, hf_pn_io_opnum);
2380         dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_supervisor, ver_pn_io_supervisor, pn_io_dissectors, hf_pn_io_opnum);
2381         dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_parameterserver, ver_pn_io_parameterserver, pn_io_dissectors, hf_pn_io_opnum);
2382
2383         heur_dissector_add("pn_rt", dissect_PNIO_heur, proto_pn_io);
2384 }