1 /* packet-pn-rsi.c
2  * Routines for PN-RSI
3  * packet dissection.
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1999 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #include "config.h"
25 
26 #include <string.h>
27 
28 #include <glib.h>
29 
30 #include <epan/packet.h>
31 #include <epan/exceptions.h>
32 #include <epan/to_str.h>
33 #include <epan/wmem_scopes.h>
34 #include <epan/dissectors/packet-dcerpc.h>
35 #include <epan/expert.h>
36 #include <epan/conversation_filter.h>
37 #include <epan/proto_data.h>
38 #include <epan/reassemble.h>
39 #include <epan/conversation.h>
40 
41 #include <wsutil/file_util.h>
42 #include <epan/prefs.h>
43 
44 #include "packet-pn.h"
45 
46 void proto_register_pn_rsi(void);
47 void proto_reg_handoff_pn_rsi(void);
48 
49 static int proto_pn_rsi = -1;
50 
51 static int hf_pn_rsi_dst_srv_access_point = -1;
52 static int hf_pn_rsi_src_srv_access_point = -1;
53 
54 static int hf_pn_rsi_pdu_type = -1;
55 static int hf_pn_rsi_pdu_type_type = -1;
56 static int hf_pn_rsi_pdu_type_version = -1;
57 
58 static int hf_pn_rsi_add_flags = -1;
59 static int hf_pn_rsi_add_flags_windowsize = -1;
60 static int hf_pn_rsi_add_flags_reserved1 = -1;
61 static int hf_pn_rsi_add_flags_tack = -1;
62 static int hf_pn_rsi_add_flags_morefrag = -1;
63 static int hf_pn_rsi_add_flags_notification = -1;
64 static int hf_pn_rsi_add_flags_reserved2 = -1;
65 
66 static int hf_pn_rsi_send_seq_num = -1;
67 static int hf_pn_rsi_ack_seq_num = -1;
68 static int hf_pn_rsi_var_part_len = -1;
69 
70 static int hf_pn_rsi_f_opnum_offset = -1;
71 static int hf_pn_rsi_f_opnum_offset_offset = -1;
72 static int hf_pn_rsi_f_opnum_offset_opnum = -1;
73 static int hf_pn_rsi_f_opnum_offset_callsequence = -1;
74 
75 static int hf_pn_rsi_conn_block = -1;
76 static int hf_pn_rsi_rsp_max_length = -1;
77 static int hf_pn_rsi_vendor_id = -1;
78 static int hf_pn_rsi_device_id = -1;
79 static int hf_pn_rsi_instance_id = -1;
80 static int hf_pn_rsi_interface = -1;
81 
82 static int hf_pn_rsi_svcs_block = -1;
83 
84 static int hf_pn_rsi_number_of_entries = -1;
85 static int hf_pn_rsi_pd_rsi_instance = -1;
86 static int hf_pn_rsi_device_type = -1;
87 static int hf_pn_rsi_order_id = -1;
88 static int hf_pn_rsi_im_serial_number = -1;
89 static int hf_pn_rsi_hw_revision = -1;
90 static int hf_pn_rsi_sw_revision_prefix = -1;
91 static int hf_pn_rsi_sw_revision = -1;
92 
93 static gint ett_pn_rsi = -1;
94 static gint ett_pn_rsi_pdu_type = -1;
95 static gint ett_pn_rsi_f_opnum_offset = -1;
96 static gint ett_pn_rsi_conn_block = -1;
97 static gint ett_pn_rsi_svcs_block = -1;
98 static gint ett_pn_rsi_add_flags = -1;
99 static gint ett_pn_rsi_rta = -1;
100 static gint ett_pn_io_pd_rsi_instance = -1;
101 
102 static expert_field ei_pn_rsi_error = EI_INIT;
103 
104 static const range_string pn_rsi_alarm_endpoint[] = {
105     { 0x0000, 0x7FFF, "RSI Initiator Instance (ISAP) or RSI Responder Instance (RSAP)" },
106     { 0x8000, 0xFFFE, "Reserved" },
107     { 0xFFFF, 0xFFFF, "CON-SAP" },
108     { 0, 0, NULL }
109 };
110 
111 static const range_string pn_rsi_pdu_type_type[] = {
112     { 0x00, 0x02, "Reserved" },
113     { 0x03, 0x03, "RTA_TYPE_ACK" },
114     { 0x04, 0x04, "RTA_TYPE_ERR" },
115     { 0x05, 0x05, "RTA_TYPE_FREQ" },
116     { 0x06, 0x06, "RTA_TYPE_FRSP" },
117     { 0x07, 0x0F, "Reserved" },
118     { 0, 0, NULL }
119 };
120 
121 static const range_string pn_rsi_pdu_type_version[] = {
122     { 0x00, 0x00, "Reserved" },
123     { 0x01, 0x01, "Version 1 of the protocol" },
124     { 0x02, 0x02, "Version 2 of the protocol" },
125     { 0x03, 0X0F, "Reserved" },
126     { 0, 0, NULL }
127 };
128 
129 static const value_string pn_rsi_add_flags_windowsize[] = {
130     { 0x00, "Reserved" },
131     { 0x01, "Unknown WindowSize" },
132     { 0x02, "Smallest WindowSize" },
133     { 0x03, "Optional usable WindowSize" },
134     { 0x04, "Optional usable WindowSize" },
135     { 0x05, "Optional usable WindowSize" },
136     { 0x06, "Optional usable WindowSize" },
137     { 0x07, "Optional usable WindowSize" },
138     { 0, NULL }
139 };
140 
141 static const value_string pn_rsi_add_flags_tack[] = {
142     { 0x00, "No immediate acknowledge" },
143     { 0x01, "Immediate acknowledge" },
144     { 0, NULL }
145 };
146 
147 static const value_string pn_rsi_add_flags_morefrag[] = {
148     { 0x00, "Last fragment" },
149     { 0x01, "More fragments follows" },
150     { 0, NULL }
151 };
152 
153 static const value_string pn_rsi_add_flags_notification[] = {
154     { 0x00, "No action necessary" },
155     { 0x01, "The ApplicationReadyBlock is available for reading with the service ReadNotification" },
156     { 0, NULL }
157 };
158 
159 static const range_string pn_rsi_seq_num[] = {
160     { 0x0000, 0x7FFF, "synchronization and transmission between initiator and responder" },
161     { 0x8000, 0xFFFD, "Reserved" },
162     { 0xFFFE, 0xFFFE, "synchronize initiator and responder for establishment of an AR" },
163     { 0xFFFF, 0xFFFF, "Reserved" },
164     { 0, 0, NULL }
165 };
166 
167 static const range_string pn_rsi_var_part_len[] = {
168     { 0x0000, 0x0000, "No RTA-SDU or RSI-SDU exists" },
169     { 0x0001, 0x0598, "An RTA-SDU or RSI-PDU with VarPartLen octets exists" },
170     { 0x0599, 0xFFFF, "Reserved" },
171     { 0, 0, NULL }
172 };
173 
174 static const range_string pn_rsi_f_opnum_offset_offset[] = {
175     { 0x00000000, 0x00000000, "First fragment" },
176     { 0x00000001, 0x00000003, "Reserved" },
177     { 0x00000004, 0x00FFFFFF, "Not first fragment" },
178     { 0, 0, NULL }
179 };
180 
181 static const value_string pn_rsi_f_opnum_offset_opnum[] = {
182     { 0x00, "Connect" },
183     { 0x01, "Reserved" },
184     { 0x02, "Read" },
185     { 0x03, "Write" },
186     { 0x04, "Control" },
187     { 0x05, "ReadImplicit" },
188     { 0x06, "ReadConnectionless" },
189     { 0x07, "ReadNotification" },
190     { 0x08, "PrmWriteMore" },
191     { 0x09, "PrmWriteEnd" },
192     { 0x0A, "Reserved" },
193     { 0x0B, "Reserved" },
194     { 0x0C, "Reserved" },
195     { 0x0D, "Reserved" },
196     { 0x0E, "Reserved" },
197     { 0x0F, "Reserved" },
198     { 0x1F, "Reserved" },
199     { 0, NULL }
200 };
201 
202 static const range_string pn_rsi_f_opnum_offset_callsequence[] = {
203     { 0x00, 0x07, "Allowed values" },
204     { 0, 0, NULL }
205 };
206 
207 static const range_string pn_rsi_rsp_max_length[] = {
208     { 0x00000000, 0x00000003, "Reserved" },
209     { 0x00000004, 0x00FFFFFF, "Usable" },
210     { 0x01FFFFFF, 0xFFFFFFFF, "Reserved" },
211     { 0, 0, NULL }
212 };
213 
214 static const range_string pn_rsi_interface[] = {
215     { 0x00, 0x00, "IO device interface" },
216     { 0x01, 0x01, "Read Implicit IO device interface" },
217     { 0x02, 0x02, "CIM device interface" },
218     { 0x03, 0x03, "Read Implicit CIM device interface" },
219     { 0x04, 0xFF, "Reserved" },
220     { 0, 0, NULL }
221 };
222 
223 static int
dissect_FOpnumOffset(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,guint8 * drep _U_,guint32 * u32FOpnumOffset)224 dissect_FOpnumOffset(tvbuff_t *tvb, int offset,
225     packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, guint32 *u32FOpnumOffset)
226 {
227     proto_item *sub_item;
228     proto_tree *sub_tree;
229 
230     sub_item = proto_tree_add_item(tree, hf_pn_rsi_f_opnum_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
231     sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_f_opnum_offset);
232     dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
233         hf_pn_rsi_f_opnum_offset_offset, u32FOpnumOffset);
234     dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
235         hf_pn_rsi_f_opnum_offset_opnum, u32FOpnumOffset);
236     offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
237         hf_pn_rsi_f_opnum_offset_callsequence, u32FOpnumOffset);
238 
239     return offset;
240 }
241 
242 static int hf_pn_rsi_data_payload = -1;
243 
244 static int hf_pn_rsi_segments = -1;
245 static int hf_pn_rsi_segment = -1;
246 //static int hf_pn_rsi_data = -1;
247 static int hf_pn_rsi_segment_overlap = -1;
248 static int hf_pn_rsi_segment_overlap_conflict = -1;
249 static int hf_pn_rsi_segment_multiple_tails = -1;
250 static int hf_pn_rsi_segment_too_long_segment = -1;
251 static int hf_pn_rsi_segment_error = -1;
252 static int hf_pn_rsi_segment_count = -1;
253 static int hf_pn_rsi_reassembled_in = -1;
254 static int hf_pn_rsi_reassembled_length = -1;
255 
256 static reassembly_table pn_rsi_reassembly_table;
257 
258 void
pn_rsi_reassemble_init(void)259 pn_rsi_reassemble_init(void)
260 {
261     reassembly_table_register(&pn_rsi_reassembly_table, &addresses_reassembly_table_functions);
262 }
263 
264 static gint ett_pn_rsi_segments = -1;
265 static gint ett_pn_rsi_segment = -1;
266 //static gint ett_pn_rsi_data = -1;
267 static gint ett_pn_rsi_data_payload = -1;
268 
269 static const fragment_items pn_rsi_frag_items = {
270     &ett_pn_rsi_segment,
271     &ett_pn_rsi_segments,
272     &hf_pn_rsi_segments,
273     &hf_pn_rsi_segment,
274     &hf_pn_rsi_segment_overlap,
275     &hf_pn_rsi_segment_overlap_conflict,
276     &hf_pn_rsi_segment_multiple_tails,
277     &hf_pn_rsi_segment_too_long_segment,
278     &hf_pn_rsi_segment_error,
279     &hf_pn_rsi_segment_count,
280     &hf_pn_rsi_reassembled_in,
281     &hf_pn_rsi_reassembled_length,
282     /* Reassembled data field */
283     NULL,
284     "segments"
285 };
286 
287 static int
dissect_pn_rta_remaining_user_data_bytes(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,guint8 * drep,guint32 length,guint8 u8MoreFrag,guint32 u32FOpnumOffsetOpnum,int type)288 dissect_pn_rta_remaining_user_data_bytes(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
289     proto_tree *tree, guint8 *drep, guint32 length, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOpnum, int type)
290 {
291     fragment_head  *fd_frag;
292     fragment_head  *fd_reass;
293     conversation_t *conv;
294     tvbuff_t       *next_tvb;
295     proto_item     *pn_rsi_tree_item;
296     proto_item     *payload_item = NULL;
297     proto_item     *payload_tree = NULL;
298     gboolean        update_col_info = TRUE;
299 
300     if (pinfo->srcport != 0 && pinfo->destport != 0) {
301         /* COTP over RFC1006/TCP, try reassembling */
302         conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, ENDPOINT_NONE,
303             pinfo->srcport, pinfo->destport, 0);
304         if (!conv) {
305             conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, ENDPOINT_NONE,
306                 pinfo->srcport, pinfo->destport, 0);
307         }
308 
309         /* XXX - don't know if this will work with multiple segmented Ack's in a single TCP stream */
310         fd_frag = fragment_get(&pn_rsi_reassembly_table, pinfo, conv->conv_index, NULL);
311         fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index);
312     }
313     else {
314         /* plain COTP transport (without RFC1006/TCP), try reassembling */
315         conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, ENDPOINT_NONE,
316             pinfo->clnp_srcref, pinfo->clnp_dstref, 0);
317         if (!conv) {
318             conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, ENDPOINT_NONE,
319                 pinfo->clnp_srcref, pinfo->clnp_dstref, 0);
320         }
321 
322         /* XXX - don't know if this will work with multiple segmented Ack's in a single TCP stream */
323         fd_frag = fragment_get(&pn_rsi_reassembly_table, pinfo, conv->conv_index, NULL);
324         fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index);
325     }
326 
327     /* is this packet containing a "standalone" segment? */
328     if (!u8MoreFrag && !fd_frag && !fd_reass) {
329         /* "standalone" segment, simply show payload and return */
330         offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
331         return offset;
332     }
333 
334     /* multiple segments */
335     if (!pinfo->fd->visited && conv != NULL) {
336         /* we haven't seen it before, add to list of segments */
337         fragment_add_seq_next(&pn_rsi_reassembly_table, tvb, offset, pinfo, conv->conv_index,
338             NULL /*Data comes from tvb as in packet-icmp-template.c */,
339             length,
340             u8MoreFrag);
341 
342         fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index);
343     }
344 
345     /* update display */
346     col_append_fstr(pinfo->cinfo, COL_INFO, " [%sPN IO RSI Segment]",
347         u8MoreFrag ? "" : "Last ");
348 
349     /* reassembling completed? */
350     if (fd_reass != NULL) {
351         /* is this the packet to show the reassembed payload in? */
352         if (pinfo->fd->num == fd_reass->reassembled_in) {
353             next_tvb = process_reassembled_data(tvb, 0, pinfo,
354                 "Reassembled PN IO RSI packet", fd_reass, &pn_rsi_frag_items, &update_col_info, tree);
355 
356             /* XXX - create new parent tree item "Reassembled Data Segments" */
357             payload_item = proto_tree_add_item(tree, hf_pn_rsi_data_payload, next_tvb, 0, tvb_captured_length(next_tvb), ENC_NA);
358             payload_tree = proto_item_add_subtree(payload_item, ett_pn_rsi_data_payload);
359 
360             offset = dissect_rsi_blocks(next_tvb, 0, pinfo, payload_tree, drep, u32FOpnumOffsetOpnum, type);
361 
362             /* the toplevel fragment subtree is now behind all desegmented data,
363             * move it right behind the DE2 tree item */
364             // pn_rsi_tree_item = proto_tree_get_parent(tree);
365 
366         }
367         else {
368             /* segment of a multiple segment payload */
369             proto_item *pi;
370 
371             pn_rsi_tree_item = proto_tree_get_parent(tree);
372             pi = proto_tree_add_uint(pn_rsi_tree_item, hf_pn_rsi_reassembled_in,
373                 tvb, 0, 0, fd_reass->reassembled_in);
374             PROTO_ITEM_SET_GENERATED(pi);
375         }
376     }
377 
378     return offset;
379 }
380 
381 /* dissect a PN-IO RSI SVCS block (on top of PN-RT protocol) */
382 static int
dissect_RSI_SVCS_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep,guint8 u8MoreFrag,guint32 u32FOpnumOffsetOffset,guint32 u32FOpnumOffsetOpnum)383 dissect_RSI_SVCS_block(tvbuff_t *tvb, int offset,
384     packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
385 {
386     proto_item *sub_item;
387     proto_tree *sub_tree;
388 
389     guint32 u32RspMaxLength;
390 
391     sub_item = proto_tree_add_item(tree, hf_pn_rsi_svcs_block, tvb, offset, 0, ENC_NA);
392     sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_svcs_block);
393     if (u32FOpnumOffsetOffset == 0)
394     {
395         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
396             hf_pn_rsi_rsp_max_length, &u32RspMaxLength);
397     }
398     else if (u8MoreFrag == 0)
399     {
400         proto_item_append_text(sub_item, ", RSI Header of SVCS is at first segment");
401     }
402 
403     offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep,
404         tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ);
405     return offset;
406 }
407 
408 /* dissect a PN-IO RSI CONN block (on top of PN-RT protocol) */
409 static int
dissect_RSI_CONN_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep,guint8 u8MoreFrag,guint32 u32FOpnumOffsetOffset,guint32 u32FOpnumOffsetOpnum)410 dissect_RSI_CONN_block(tvbuff_t *tvb, int offset,
411     packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
412 {
413     proto_item *sub_item;
414     proto_tree *sub_tree;
415 
416     guint32 u32RspMaxLength;
417     guint16 u16VendorId;
418     guint16 u16DeviceId;
419     guint16 u16InstanceId;
420     guint8  u8RsiInterface;
421 
422     sub_item = proto_tree_add_item(tree, hf_pn_rsi_conn_block, tvb, offset, 0, ENC_NA);
423     sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_conn_block);
424 
425     if (u32FOpnumOffsetOffset == 0) {
426 
427         offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
428             hf_pn_rsi_rsp_max_length, &u32RspMaxLength);
429         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
430             hf_pn_rsi_vendor_id, &u16VendorId);
431         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
432             hf_pn_rsi_device_id, &u16DeviceId);
433         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
434             hf_pn_rsi_instance_id, &u16InstanceId);
435         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
436             hf_pn_rsi_interface, &u8RsiInterface);
437 
438         offset = dissect_pn_padding(tvb, offset, pinfo, sub_tree, 1);
439     }
440     else if (u8MoreFrag == 0)
441     {
442         proto_item_append_text(sub_item, ", RSI Header of CONN is at first segment");
443     }
444 
445     offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep,
446         tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ);
447 
448     return offset;
449 }
450 
451 /* dissect a PN-IO RSI FREQ RTA PDU (on top of PN-RT protocol) */
452 static int
dissect_FREQ_RTA_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep,guint8 u8MoreFrag)453 dissect_FREQ_RTA_block(tvbuff_t *tvb, int offset,
454     packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag)
455 {
456     guint32    u32FOpnumOffset;
457     guint32    u32FOpnumOffsetOpnum;
458     guint32    u32FOpnumOffsetOffset;
459     offset = dissect_FOpnumOffset(tvb, offset, pinfo, tree, drep, &u32FOpnumOffset);
460     u32FOpnumOffsetOpnum = (u32FOpnumOffset & 0x1F000000) >> 24;
461     u32FOpnumOffsetOffset = u32FOpnumOffset & 0x00FFFFFF;
462     switch (u32FOpnumOffsetOpnum) {
463     case(0x0):    /* RSI-CONN-PDU */
464         col_append_str(pinfo->cinfo, COL_INFO, "Connect request");
465         offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
466         break;
467     case(0x1):    /* Reserved */
468         col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
469         offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb));
470         break;
471     case(0x2):    /* RSI-SVCS-PDU (Only valid with ARUUID<>0) */
472         col_append_str(pinfo->cinfo, COL_INFO, "Read request");
473         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
474         break;
475     case(0x3):    /* RSI-SVCS-PDU */
476         col_append_str(pinfo->cinfo, COL_INFO, "Write request");
477         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
478         break;
479     case(0x4):    /* RSI-SVCS-PDU */
480         col_append_str(pinfo->cinfo, COL_INFO, "Control request");
481         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
482         break;
483     case(0x5):    /* RSI-CONN-PDU (Only valid with ARUUID=0) */
484         col_append_str(pinfo->cinfo, COL_INFO, "ReadImplicit request");
485         offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
486         break;
487     case(0x6):    /* RSI-CONN-PDU (Only valid with ARUUID<>0) */
488         col_append_str(pinfo->cinfo, COL_INFO, "ReadConnectionless request");
489         offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
490         break;
491     case(0x7):    /* RSI-SVCS-PDU */
492         col_append_str(pinfo->cinfo, COL_INFO, "ReadNotification request");
493         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
494         break;
495     case(0x8):    /* RSI-SVCS-PDU */
496         col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteMore request");
497         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
498         break;
499     case(0x9) :    /* RSI-SVCS-PDU */
500         col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteEnd request");
501         offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
502         break;
503     default:
504         col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
505         offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb));
506         break;
507     }
508     return offset;
509 }
510 
511 /* dissect a PN-IO RSI RSP block (on top of PN-RT protocol) */
512 static int
dissect_RSI_RSP_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep,guint16 u16VarPartLen,guint8 u8MoreFrag,guint32 u32FOpnumOffsetOffset,guint32 u32FOpnumOffsetOpnum)513 dissect_RSI_RSP_block(tvbuff_t *tvb, int offset,
514     packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
515 {
516     guint32 u32RsiHeaderSize = 4;
517 
518     // PDU.FOpnumOffset.Offset + PDU.VarPartLen - 4 - RsiHeaderSize
519     gint32 length = u32FOpnumOffsetOffset + u16VarPartLen - 4 - u32RsiHeaderSize;
520 
521     if (u32FOpnumOffsetOffset == 0)
522     {
523         offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
524     }
525 
526     else if (u8MoreFrag == 0)
527     {
528         proto_item_append_text(tree, ", RSI Header of RSP is at first fragmented frame");
529     }
530 
531     if (length > 0) {
532         offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, tree, drep,
533             tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_RSP);
534     }
535 
536     return offset;
537 }
538 
539 /* dissect a PN-IO RSI FRSP RTA PDU (on top of PN-RT protocol) */
540 static int
dissect_FRSP_RTA_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep,guint16 u16VarPartLen,guint8 u8MoreFrag)541 dissect_FRSP_RTA_block(tvbuff_t *tvb, int offset,
542     packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag)
543 {
544     guint32    u32FOpnumOffset;
545     guint32    u32FOpnumOffsetOpnum;
546     guint32    u32FOpnumOffsetOffset;
547     offset = dissect_FOpnumOffset(tvb, offset, pinfo, tree, drep, &u32FOpnumOffset);
548     u32FOpnumOffsetOpnum = (u32FOpnumOffset & 0x1F000000) >> 24;
549     u32FOpnumOffsetOffset = u32FOpnumOffset & 0x00FFFFFF;
550     switch (u32FOpnumOffsetOpnum) {
551     case(0x0):    /* Connect */
552         col_append_str(pinfo->cinfo, COL_INFO, "Connect response");
553         break;
554     case(0x1):    /* Reserved */
555         col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
556         break;
557     case(0x2):    /* Read */
558         col_append_str(pinfo->cinfo, COL_INFO, "Read response");
559         break;
560     case(0x3):    /* Write */
561         col_append_str(pinfo->cinfo, COL_INFO, "Write response");
562         break;
563     case(0x4):    /* Control */
564         col_append_str(pinfo->cinfo, COL_INFO, "Control response");
565         break;
566     case(0x5):    /* ReadImplicit */
567         col_append_str(pinfo->cinfo, COL_INFO, "ReadImplicit response");
568         break;
569     case(0x6):    /* ReadConnectionless */
570         col_append_str(pinfo->cinfo, COL_INFO, "ReadConnectionless response");
571         break;
572     case(0x7):    /* ReadNotification */
573         col_append_str(pinfo->cinfo, COL_INFO, "ReadNotification response");
574         break;
575     case(0x8):    /* PrmWriteMore */
576         col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteMore response");
577         break;
578     case(0x9) :   /* PrmWriteEnd */
579         col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteEnd response");
580         break;
581     default:
582         col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
583         break;
584     }
585     offset = dissect_RSI_RSP_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
586     return offset;
587 }
588 
589 static int
dissect_RSIAdditionalFlags(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,guint8 * drep _U_,guint8 * u8AddFlags)590 dissect_RSIAdditionalFlags(tvbuff_t *tvb, int offset,
591     packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, guint8 *u8AddFlags)
592 {
593     guint8      u8WindowSize;
594     guint8      u8Tack;
595     proto_item *sub_item;
596     proto_tree *sub_tree;
597 
598     /* additional flags */
599     sub_item = proto_tree_add_item(tree, hf_pn_rsi_add_flags, tvb, offset, 1, ENC_NA);
600     sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_add_flags);
601     /* Bit 0 - 2 : AddFlags.WindowSize */
602     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
603         hf_pn_rsi_add_flags_windowsize, u8AddFlags);
604     /* Bit 3: AddFlags.Reserved */
605     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
606         hf_pn_rsi_add_flags_reserved1, u8AddFlags);
607     /* Bit 4:  AddFlags.TACK */
608     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
609         hf_pn_rsi_add_flags_tack, u8AddFlags);
610     /* Bit 5:  AddFlags.MoreFrag */
611     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
612         hf_pn_rsi_add_flags_morefrag, u8AddFlags);
613     /* Bit 6: AddFlags.Notification */
614     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
615         hf_pn_rsi_add_flags_notification, u8AddFlags);
616     /* Bit 7: AddFlags.Reserved */
617     offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
618         hf_pn_rsi_add_flags_reserved2, u8AddFlags);
619     u8WindowSize = *u8AddFlags & 0x03;
620     u8Tack = (*u8AddFlags & 0x10);
621     u8Tack = (u8Tack == 0x10) ? 1 : 0;
622 
623     proto_item_append_text(sub_item, ", Window Size: %u, Tack: %u  ",
624         u8WindowSize, u8Tack);
625     return offset;
626 }
627 
628 /* dissect a PN-IO RTA RSI PDU (on top of PN-RT protocol) */
629 int
dissect_PNIO_RSI(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint8 * drep)630 dissect_PNIO_RSI(tvbuff_t *tvb, int offset,
631     packet_info *pinfo, proto_tree *tree, guint8 *drep)
632 {
633     guint16     u16DestinationServiceAccessPoint;
634     guint16     u16SourceServiceAccessPoint;
635     guint8      u8PDUType;
636     guint8      u8PDUVersion;
637     guint8      u8AddFlags;
638     guint8      u8MoreFrag;
639     guint16     u16SendSeqNum;
640     guint16     u16AckSeqNum;
641     guint16     u16VarPartLen;
642     int         start_offset = offset;
643 
644     proto_item *rta_item;
645     proto_tree *rta_tree;
646 
647     proto_item *sub_item;
648     proto_tree *sub_tree;
649 
650     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-RSI");
651     rta_item = proto_tree_add_protocol_format(tree, proto_pn_rsi, tvb, offset, tvb_captured_length(tvb),
652         "PROFINET IO RSI");
653 
654     rta_tree = proto_item_add_subtree(rta_item, ett_pn_rsi_rta);
655 
656     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
657         hf_pn_rsi_dst_srv_access_point, &u16DestinationServiceAccessPoint);
658     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
659         hf_pn_rsi_src_srv_access_point, &u16SourceServiceAccessPoint);
660 
661     //col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: 0x%x, Dst: 0x%x",
662     //    u16SourceServiceAccessPoint, u16DestinationServiceAccessPoint);
663 
664     /* PDU type */
665     sub_item = proto_tree_add_item(rta_tree, hf_pn_rsi_pdu_type, tvb, offset, 1, ENC_NA);
666     sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_pdu_type);
667 
668     /* PDU type type - version of RTA 2*/
669     dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
670         hf_pn_rsi_pdu_type_type, &u8PDUType);
671     u8PDUType &= 0x0F;
672 
673     /* PDU type version - version of RTA 2*/
674     offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
675         hf_pn_rsi_pdu_type_version, &u8PDUVersion);
676     u8PDUVersion >>= 4;
677     //proto_item_append_text(sub_item, ", Type: %s, Version: %u",
678     //    val_to_str(u8PDUType, pn_rsi_pdu_type_type, "Unknown"),
679     //    u8PDUVersion);
680     offset = dissect_RSIAdditionalFlags(tvb, offset, pinfo, rta_tree, drep, &u8AddFlags);
681     u8MoreFrag = (u8AddFlags >> 5) & 0x1;
682     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
683         hf_pn_rsi_send_seq_num, &u16SendSeqNum);
684     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
685         hf_pn_rsi_ack_seq_num, &u16AckSeqNum);
686     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
687         hf_pn_rsi_var_part_len, &u16VarPartLen);
688 
689     switch (u8PDUType & 0x0F) {
690     case(3):    /* ACK-RTA */
691         col_append_str(pinfo->cinfo, COL_INFO, "ACK-RTA");
692 
693         if (u8AddFlags & 0x40) {
694 
695             col_append_str(pinfo->cinfo, COL_INFO, ", Application Ready Notification");
696         }
697         /* no additional data */
698         break;
699     case(4):    /* ERR-RTA */
700         col_append_str(pinfo->cinfo, COL_INFO, "ERR-RTA");
701         offset = dissect_PNIO_status(tvb, offset, pinfo, rta_tree, drep);
702         break;
703     case(5):    /* FREQ-RTA */
704         offset = dissect_FREQ_RTA_block(tvb, offset, pinfo, rta_tree, drep, u8MoreFrag);
705         break;
706     case(6):    /* FRSP-RTA */
707         offset = dissect_FRSP_RTA_block(tvb, offset, pinfo, rta_tree, drep, u16VarPartLen, u8MoreFrag);
708         break;
709     default:
710         offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb));
711         break;
712     }
713 
714     proto_item_set_len(rta_item, offset - start_offset);
715 
716     return offset;
717 }
718 
719 int
dissect_PDRsiInstances_block(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,proto_item * item _U_,guint8 * drep,guint8 u8BlockVersionHigh,guint8 u8BlockVersionLow)720 dissect_PDRsiInstances_block(tvbuff_t *tvb, int offset,
721     packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow)
722 {
723     proto_item *sub_item;
724     proto_tree *sub_tree;
725     guint16    u16NumberOfEntries;
726     guint16    u16VendorId;
727     guint16    u16DeviceId;
728     guint16    u16InstanceId;
729     guint8     u8RsiInterface;
730     const int  deviceType_size       = 25;
731     const int  orderID_size          = 20;
732     const int  IMserialnumber_size   = 16;
733     const int  HWrevision_size       = 5;
734     const int  SWrevisionprefix_size = 1;
735     const int  SWrevision_size       = 9;
736     char      *deviceType;
737     char      *orderID;
738     char      *IMserialnumber;
739     char      *HWrevision;
740     char      *SWrevisionprefix;
741     char      *SWrevision;
742 
743     if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) {
744         expert_add_info_format(pinfo, item, &ei_pn_rsi_error,
745             "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow);
746         return offset;
747     }
748 
749     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
750         hf_pn_rsi_number_of_entries, &u16NumberOfEntries);
751 
752     proto_item_append_text(item, ": NumberOfEntries:%u", u16NumberOfEntries);
753 
754     while (u16NumberOfEntries > 0) {
755         u16NumberOfEntries--;
756 
757         sub_item = proto_tree_add_item(tree, hf_pn_rsi_pd_rsi_instance, tvb, offset, 0, ENC_NA);
758         sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pd_rsi_instance);
759         /* VendorID */
760         /* DeviceID */
761         /* InstanceID */
762         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
763             hf_pn_rsi_vendor_id, &u16VendorId);
764         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
765             hf_pn_rsi_device_id, &u16DeviceId);
766         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
767             hf_pn_rsi_instance_id, &u16InstanceId);
768 
769         /* RSI Interface */
770         offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
771             hf_pn_rsi_interface, &u8RsiInterface);
772 
773         proto_item_append_text(sub_item, ": VendorID:%u, DeviceID:%u, InstanceID:%u, RsiInterface:%u",
774             u16VendorId, u16DeviceId, u16InstanceId, u8RsiInterface);
775 
776         /* Padding */
777         offset = dissect_pn_padding(tvb, offset, pinfo, sub_tree, 1);
778     }
779 
780     /* SystemIdentification */
781     /* DeviceType */
782     deviceType = (char *)wmem_alloc(pinfo->pool, deviceType_size + 1);
783     tvb_memcpy(tvb, (guint8 *)deviceType, offset, 25);
784     deviceType[deviceType_size] = '\0';
785     proto_tree_add_string(tree, hf_pn_rsi_device_type, tvb, offset, deviceType_size, deviceType);
786     offset += deviceType_size + 1;
787 
788     /* Blank */
789 
790     /* OrderID */
791     orderID = (char *)wmem_alloc(pinfo->pool, orderID_size + 1);
792     tvb_memcpy(tvb, (guint8 *)orderID, offset, 20);
793     orderID[orderID_size] = '\0';
794     proto_tree_add_string(tree, hf_pn_rsi_order_id, tvb, offset, orderID_size, orderID);
795     offset += orderID_size + 1;
796 
797     /* Blank */
798 
799     /* IM_Serial_Number */
800     IMserialnumber = (char *)wmem_alloc(pinfo->pool, IMserialnumber_size + 1);
801     tvb_memcpy(tvb, (guint8 *)IMserialnumber, offset, 16);
802     IMserialnumber[IMserialnumber_size] = '\0';
803     proto_tree_add_string(tree, hf_pn_rsi_im_serial_number, tvb, offset, IMserialnumber_size, IMserialnumber);
804     offset += IMserialnumber_size + 1;
805 
806     /* Blank */
807 
808     /* HWRevision */
809     HWrevision = (char *)wmem_alloc(pinfo->pool, HWrevision_size + 1);
810     tvb_memcpy(tvb, (guint8 *)HWrevision, offset, 5);
811     HWrevision[HWrevision_size] = '\0';
812     proto_tree_add_string(tree, hf_pn_rsi_hw_revision, tvb, offset, HWrevision_size, HWrevision);
813     offset += HWrevision_size + 1;
814 
815     /* Blank */
816 
817     /* SWRevisionPrefix */
818     SWrevisionprefix = (char *)wmem_alloc(pinfo->pool, SWrevisionprefix_size + 1);
819     tvb_memcpy(tvb, (guint8 *)SWrevisionprefix, offset, 1);
820     SWrevisionprefix[SWrevisionprefix_size] = '\0';
821     proto_tree_add_string(tree, hf_pn_rsi_sw_revision_prefix, tvb, offset, SWrevisionprefix_size, SWrevisionprefix);
822     offset += SWrevisionprefix_size;
823 
824     /* SWRevision */
825     SWrevision = (char *)wmem_alloc(pinfo->pool, SWrevision_size + 1);
826     tvb_memcpy(tvb, (guint8 *)SWrevision, offset, 9);
827     SWrevision[SWrevision_size] = '\0';
828     proto_tree_add_string(tree, hf_pn_rsi_sw_revision, tvb, offset, SWrevision_size, SWrevision);
829     offset += SWrevision_size;
830     return offset;
831 }
832 
833 void
init_pn_rsi(int proto)834 init_pn_rsi(int proto)
835 {
836     static hf_register_info hf[] = {
837         { &hf_pn_rsi_dst_srv_access_point,
838         { "DestinationServiceAccessPoint", "pn_rsi.dst_srv_access_point",
839         FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_alarm_endpoint), 0x0,
840         NULL, HFILL }
841         },
842         { &hf_pn_rsi_src_srv_access_point,
843         { "SourceServiceAccessPoint", "pn_rsi.src_srv_access_point",
844         FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_alarm_endpoint), 0x0,
845         NULL, HFILL }
846         },
847         { &hf_pn_rsi_pdu_type,
848         { "PDUType", "pn_rsi.pdu_type",
849         FT_NONE, BASE_NONE, NULL, 0x0,
850         NULL, HFILL }
851         },
852         { &hf_pn_rsi_pdu_type_type,
853         { "Type", "pn_rsi.pdu_type.type",
854         FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_pdu_type_type), 0x0F,
855         NULL, HFILL }
856         },
857         { &hf_pn_rsi_pdu_type_version,
858         { "Version", "pn_rsi.pdu_type.version",
859         FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_pdu_type_version), 0xF0,
860         NULL, HFILL }
861         },
862         { &hf_pn_rsi_add_flags,
863         { "AddFlags", "pn_rsi.add_flags",
864         FT_NONE, BASE_NONE, NULL, 0x0,
865         NULL, HFILL }
866         },
867         { &hf_pn_rsi_add_flags_windowsize,
868         { "WindowSize", "pn_rsi.add_flags_windowsize",
869         FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_windowsize), 0x07,
870         NULL, HFILL }
871         },
872         { &hf_pn_rsi_add_flags_reserved1,
873         { "Reserved", "pn_rsi.add_flags_reserved",
874         FT_UINT8, BASE_HEX, NULL, 0x08,
875         NULL, HFILL }
876         },
877         { &hf_pn_rsi_add_flags_tack,
878         { "TACK", "pn_rsi.add_flags_tack",
879         FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_tack), 0x10,
880         NULL, HFILL }
881         },
882         { &hf_pn_rsi_add_flags_morefrag,
883         { "MoreFrag", "pn_rsi.add_flags_morefrag",
884         FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_morefrag), 0x20,
885         NULL, HFILL }
886         },
887         { &hf_pn_rsi_add_flags_notification,
888         { "Notification", "pn_rsi.add_flags_notification",
889         FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_notification), 0x40,
890         NULL, HFILL }
891         },
892         { &hf_pn_rsi_add_flags_reserved2,
893         { "Reserved", "pn_rsi.add_flags_reserved",
894         FT_UINT8, BASE_HEX, NULL, 0x80,
895         NULL, HFILL }
896         },
897         { &hf_pn_rsi_send_seq_num,
898         { "SendSeqNum", "pn_rsi.send_seq_num",
899         FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_seq_num), 0x0,
900         NULL, HFILL }
901         },
902         { &hf_pn_rsi_ack_seq_num,
903         { "AckSeqNum", "pn_rsi.ack_seq_num",
904         FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_seq_num), 0x0,
905         NULL, HFILL }
906         },
907         { &hf_pn_rsi_var_part_len,
908         { "VarPartLen", "pn_rsi.var_part_len",
909         FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_var_part_len), 0x0,
910         NULL, HFILL }
911         },
912         { &hf_pn_rsi_f_opnum_offset,
913         { "FOpnumOffset", "pn_rsi.f_opnum_offset",
914         FT_UINT32, BASE_HEX, NULL, 0x0,
915         NULL, HFILL }
916         },
917         { &hf_pn_rsi_f_opnum_offset_offset,
918         { "FOpnumOffset.Offset", "pn_rsi.f_opnum_offset.offset",
919         FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_f_opnum_offset_offset), 0x00FFFFFF,
920         NULL, HFILL }
921         },
922         { &hf_pn_rsi_f_opnum_offset_opnum,
923         { "FOpnumOffset.Opnum", "pn_rsi.f_opnum_offset.opnum",
924         FT_UINT32, BASE_HEX, VALS(pn_rsi_f_opnum_offset_opnum), 0x1F000000,
925         NULL, HFILL }
926         },
927         { &hf_pn_rsi_f_opnum_offset_callsequence,
928         { "FOpnumOffset.CallSequence", "pn_rsi.f_opnum_offset.callsequence",
929         FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_f_opnum_offset_callsequence), 0xE0000000,
930         NULL, HFILL }
931         },
932         { &hf_pn_rsi_conn_block,
933         { "RSI CONN Block", "pn_rsi.conn_block",
934         FT_NONE, BASE_NONE, NULL, 0x0,
935         NULL, HFILL }
936         },
937         { &hf_pn_rsi_rsp_max_length,
938         { "RspMaxLength", "pn_rsi.rsp_max_length",
939             FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_rsp_max_length), 0x0,
940             NULL, HFILL }
941         },
942         { &hf_pn_rsi_vendor_id,
943         { "VendorID", "pn_rsi.vendor_id",
944             FT_UINT16, BASE_HEX, NULL, 0x0,
945             NULL, HFILL }
946         },
947         { &hf_pn_rsi_device_id,
948         { "DeviceID", "pn_rsi.device_id",
949             FT_UINT16, BASE_HEX, NULL, 0x0,
950             NULL, HFILL }
951         },
952         { &hf_pn_rsi_instance_id,
953         { "InstanceID", "pn_rsi.instance_id",
954             FT_UINT16, BASE_HEX, NULL, 0x0,
955             NULL, HFILL }
956         },
957         { &hf_pn_rsi_interface,
958         { "RsiInterface", "pn_rsi.interface",
959             FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_interface), 0x0,
960             NULL, HFILL }
961         },
962         { &hf_pn_rsi_svcs_block,
963         { "RSI SVCS Block", "pn_rsi.svcs_block",
964             FT_NONE, BASE_NONE, NULL, 0x0,
965             NULL, HFILL }
966         },
967         { &hf_pn_rsi_number_of_entries,
968           { "NumberOfEntries", "pn_rsi.number_of_entries",
969             FT_UINT16, BASE_HEX, NULL, 0x0,
970             NULL, HFILL }
971         },
972         { &hf_pn_rsi_pd_rsi_instance,
973           { "PDRsiInstance", "pn_rsi.pd_rsi_instance",
974             FT_NONE, BASE_NONE, NULL, 0x0,
975             NULL, HFILL }
976         },
977         { &hf_pn_rsi_device_type,
978           { "DeviceType", "pn_rsi.device_type",
979             FT_STRING, BASE_NONE, NULL, 0x0,
980             NULL, HFILL }
981         },
982         { &hf_pn_rsi_order_id,
983           { "OrderID", "pn_rsi.order_id",
984             FT_STRING, BASE_NONE, NULL, 0x0,
985             NULL, HFILL }
986         },
987         { &hf_pn_rsi_im_serial_number,
988           { "IM_Serial_Number", "pn_rsi.im_serial_number",
989             FT_STRING, BASE_NONE, NULL, 0x0,
990             NULL, HFILL }
991         },
992         { &hf_pn_rsi_hw_revision,
993           { "HWRevision", "pn_rsi.hw_revision",
994             FT_STRING, BASE_NONE, NULL, 0x0,
995             NULL, HFILL }
996         },
997         { &hf_pn_rsi_sw_revision_prefix,
998           { "SWRevisionPrefix", "pn_rsi.sw_revision_prefix",
999             FT_STRING, BASE_NONE, NULL, 0x0,
1000             NULL, HFILL }
1001         },
1002         { &hf_pn_rsi_sw_revision,
1003           { "SWRevision", "pn_rsi.sw_revision",
1004             FT_STRING, BASE_NONE, NULL, 0x0,
1005             NULL, HFILL }
1006         },
1007             /*&hf_pn_rsi_segment_too_long_segment,
1008             &hf_pn_rsi_segment_error,
1009             &hf_pn_rsi_segment_count,
1010             &hf_pn_rsi_reassembled_in,
1011             &hf_pn_rsi_reassembled_length,*/
1012         { &hf_pn_rsi_segment,
1013           { "RSI Segment", "pn_rsi.segment",
1014             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1015             NULL, HFILL }
1016         },
1017         { &hf_pn_rsi_segments,
1018           { "PN RSI Segments", "pn_rsi.segments",
1019             FT_NONE, BASE_NONE, NULL, 0x0,
1020             NULL, HFILL }
1021         },
1022         { &hf_pn_rsi_segment_overlap,
1023           { "Segment overlap", "pn_rsi.segment.overlap",
1024             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1025             "Segment overlaps with other segments", HFILL }
1026         },
1027         { &hf_pn_rsi_segment_overlap_conflict,
1028           { "Conflicting data in segment overlap", "pn_rsi.segment.overlap.conflict",
1029             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1030             "Overlapping segments contained conflicting data", HFILL }
1031         },
1032         { &hf_pn_rsi_segment_multiple_tails,
1033           { "Multiple tail segments found", "pn_rsi.segment.multipletails",
1034             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1035             "Several tails were found when reassembling the packet", HFILL }
1036         },
1037         { &hf_pn_rsi_segment_too_long_segment,
1038           { "Segment too long", "pn_rsi.segment.toolongsegment",
1039             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1040             "Segment contained data past end of packet", HFILL }
1041         },
1042         { &hf_pn_rsi_segment_error,
1043           { "Reassembly error", "pn_rsi.segment.error",
1044             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1045             "Reassembly error due to illegal segments", HFILL }
1046         },
1047         { &hf_pn_rsi_segment_count,
1048           { "Segment count", "pn_rsi.segment.count",
1049             FT_UINT32, BASE_DEC, NULL, 0x0,
1050             NULL, HFILL }
1051         },
1052         { &hf_pn_rsi_reassembled_in,
1053           { "Reassembled pn_rsi in frame", "pn_rsi.reassembled_in",
1054             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1055             "This pn_rsi packet is reassembled in this frame", HFILL }
1056         },
1057         { &hf_pn_rsi_reassembled_length,
1058           { "Reassembled pn_rsi length", "pn_rsi.reassembled.length",
1059             FT_UINT32, BASE_DEC, NULL, 0x0,
1060             "The total length of the reassembled payload", HFILL }
1061         },
1062         { &hf_pn_rsi_data_payload,
1063           { "PN IO RSI Data Payload", "pn_rsi.data_payload",
1064             FT_NONE, BASE_NONE, NULL, 0x0,
1065             "", HFILL }
1066         }
1067     };
1068 
1069     static gint *ett[] = {
1070         &ett_pn_rsi,
1071         &ett_pn_rsi_pdu_type,
1072         &ett_pn_rsi_f_opnum_offset,
1073         &ett_pn_rsi_conn_block,
1074         &ett_pn_rsi_svcs_block,
1075         &ett_pn_rsi_add_flags,
1076         &ett_pn_rsi_rta,
1077         &ett_pn_io_pd_rsi_instance,
1078         &ett_pn_rsi_segments,
1079         &ett_pn_rsi_segment,
1080         &ett_pn_rsi_data_payload
1081     };
1082 
1083     static ei_register_info ei[] = {
1084         { &ei_pn_rsi_error, { "pn_rsi.ack_seq_num", PI_UNDECODED, PI_NOTE, "Block version not implemented yet!", EXPFILL } }
1085 
1086     };
1087 
1088     expert_module_t* expert_pn_rsi;
1089 
1090     proto_pn_rsi = proto;
1091 
1092     proto_register_field_array(proto, hf, array_length(hf));
1093     proto_register_subtree_array(ett, array_length(ett));
1094     expert_pn_rsi = expert_register_protocol(proto_pn_rsi);
1095     expert_register_field_array(expert_pn_rsi, ei, array_length(ei));
1096 
1097     register_init_routine(pn_rsi_reassemble_init);
1098 }
1099