2 * Routines for PN-DCP (PROFINET Discovery and basic Configuration Protocol)
5 * IEC 61158-6-10 section 4.3
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1999 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
15 * Cyclic PNIO RTC1 Data Dissection:
17 * Added new functions to packet-pn-dcp.c. The profinet plug-in will now save
18 * the information (Stationname, -type, -id) of "Ident OK" frames. Those
19 * informations will later be used for detailed dissection of cyclic PNIO RTC1
22 * The declaration of the new added structures are within packet-pn.h to
23 * use the information within packet-pn-rtc-one.c
25 * Overview for cyclic PNIO RTC1 data dissection functions:
26 * -> dissect_PNDCP_Suboption_Device (Save Stationname, -type, -id)
34 #include <epan/packet.h>
35 #include <epan/to_str.h>
36 #include <epan/wmem_scopes.h>
37 #include <epan/expert.h>
38 #include <epan/conversation.h>
40 #include <wsutil/array.h>
42 #include "packet-pn.h"
45 void proto_register_pn_dcp(void);
46 void proto_reg_handoff_pn_dcp(void);
50 static int hf_pn_dcp_service_id
;
51 static int hf_pn_dcp_service_type
;
52 static int hf_pn_dcp_xid
;
53 static int hf_pn_dcp_reserved8
;
54 static int hf_pn_dcp_reserved16
;
55 static int hf_pn_dcp_response_delay
;
56 static int hf_pn_dcp_data_length
;
57 static int hf_pn_dcp_block_length
;
59 static int hf_pn_dcp_block
;
61 static int hf_pn_dcp_block_error
;
63 static int hf_pn_dcp_option
;
64 static int hf_pn_dcp_block_info
;
65 static int hf_pn_dcp_block_qualifier
;
66 static int hf_pn_dcp_blockqualifier
;
67 static int hf_pn_dcp_blockqualifier_r2f
;
69 static int hf_pn_dcp_suboption_ip
;
70 static int hf_pn_dcp_suboption_ip_block_info
;
71 static int hf_pn_dcp_suboption_ip_ip
;
72 static int hf_pn_dcp_suboption_ip_subnetmask
;
73 static int hf_pn_dcp_suboption_ip_standard_gateway
;
74 static int hf_pn_dcp_suboption_ip_mac_address
;
76 static int hf_pn_dcp_suboption_device
;
77 static int hf_pn_dcp_suboption_device_typeofstation
;
78 static int hf_pn_dcp_suboption_device_nameofstation
;
79 static int hf_pn_dcp_suboption_vendor_id
;
80 static int hf_pn_dcp_suboption_device_id
;
81 static int hf_pn_dcp_suboption_device_role
;
82 static int hf_pn_dcp_suboption_device_aliasname
;
83 static int hf_pn_dcp_suboption_device_instance_high
;
84 static int hf_pn_dcp_suboption_device_instance_low
;
85 static int hf_pn_dcp_suboption_device_oem_ven_id
;
86 static int hf_pn_dcp_suboption_device_oem_dev_id
;
88 static int hf_pn_dcp_rsi_properties_value
;
89 static int hf_pn_dcp_rsi_properties_value_bit0
;
90 static int hf_pn_dcp_rsi_properties_value_bit1
;
91 static int hf_pn_dcp_rsi_properties_value_bit2
;
92 static int hf_pn_dcp_rsi_properties_value_bit3
;
93 static int hf_pn_dcp_rsi_properties_value_bit4
;
94 static int hf_pn_dcp_rsi_properties_value_bit5
;
95 static int hf_pn_dcp_rsi_properties_value_otherbits
;
97 static int hf_pn_dcp_suboption_tsn
;
98 static int hf_pn_dcp_suboption_tsn_domain_name
;
99 static int hf_pn_dcp_suboption_tsn_domain_uuid
;
100 static int hf_pn_dcp_suboption_tsn_nme_prio
;
101 static int hf_pn_dcp_suboption_tsn_nme_parameter_uuid
;
102 static int hf_pn_dcp_suboption_tsn_nme_agent
;
104 static int hf_pn_dcp_suboption_dhcp
;
105 static int hf_pn_dcp_suboption_dhcp_option_code
;
106 static int hf_pn_dcp_suboption_dhcp_parameter_length
;
107 static int hf_pn_dcp_suboption_dhcp_parameter_data
;
108 static int hf_pn_dcp_suboption_dhcp_arbitrary_client_id
;
109 static int hf_pn_dcp_suboption_dhcp_control_parameter_data
;
111 static int hf_pn_dcp_suboption_control
;
112 static int hf_pn_dcp_suboption_control_option
;
113 static int hf_pn_dcp_suboption_control_signal_value
;
115 static int hf_pn_dcp_suboption_deviceinitiative
;
116 static int hf_pn_dcp_deviceinitiative_value
;
118 static int hf_pn_dcp_suboption_all
;
120 static int hf_pn_dcp_suboption_manuf
;
122 static int hf_pn_dcp_vendor_id_high
;
123 static int hf_pn_dcp_vendor_id_low
;
124 static int hf_pn_dcp_device_id_high
;
125 static int hf_pn_dcp_device_id_low
;
126 static int hf_pn_dcp_instance_id_high
;
127 static int hf_pn_dcp_instance_id_low
;
128 static int ett_pn_dcp
;
129 static int ett_pn_dcp_block
;
131 static int ett_pn_dcp_rsi_properties_value
;
133 static expert_field ei_pn_dcp_block_parse_error
;
134 static expert_field ei_pn_dcp_block_error_unknown
;
135 static expert_field ei_pn_dcp_ip_conflict
;
137 #define PNDCP_SERVICE_ID_GET 0x03
138 #define PNDCP_SERVICE_ID_SET 0x04
139 #define PNDCP_SERVICE_ID_IDENTIFY 0x05
140 #define PNDCP_SERVICE_ID_HELLO 0x06
142 static const value_string pn_dcp_service_id
[] = {
143 { 0x00, "reserved" },
144 { 0x01, "Manufacturer specific" },
145 { 0x02, "Manufacturer specific" },
146 { PNDCP_SERVICE_ID_GET
, "Get" },
147 { PNDCP_SERVICE_ID_SET
, "Set" },
148 { PNDCP_SERVICE_ID_IDENTIFY
,"Identify" },
149 { PNDCP_SERVICE_ID_HELLO
, "Hello" },
150 /* 0x07 - 0xff reserved */
154 #define PNDCP_SERVICE_TYPE_REQUEST 0
155 #define PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS 1
156 #define PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED 5
158 static const value_string pn_dcp_service_type
[] = {
159 { PNDCP_SERVICE_TYPE_REQUEST
, "Request" },
160 { PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS
, "Response Success" },
161 { PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED
, "Response - Request not supported" },
162 /* all others reserved */
166 static const value_string pn_dcp_block_error
[] = {
168 { 0x01, "Option unsupp." },
169 { 0x02, "Suboption unsupp. or no DataSet avail." },
170 { 0x03, "Suboption not set" },
171 { 0x04, "Resource Error" },
172 { 0x05, "SET not possible by local reasons" },
173 { 0x06, "In operation, SET not possible" },
174 /* all others reserved */
178 static const range_string pn_dcp_block_info
[] = {
179 { 0x0000, 0xFFFF, "Reserved" },
183 static const value_string pn_dcp_block_qualifier
[] = {
184 { 0x0000, "Use the value temporary" },
185 { 0x0001, "Save the value permanent" },
186 /*0x0002 - 0xffff reserved */
190 static const value_string pn_dcp_BlockQualifier
[] = {
191 { 0x0002, "Reset application data" },
192 { 0x0003, "Reset application data" },
193 { 0x0004, "Reset communication parameter" },
194 { 0x0005, "Reset communication parameter" },
195 { 0x0006, "Reset engineering parameter" },
196 { 0x0007, "Reset engineering parameter" },
197 { 0x0008, "Resets all stored data" },
198 { 0x0009, "Resets all stored data" },
199 { 0x000A, "Reset engineering parameter" },
200 { 0x000B, "Reset engineering parameter" },
201 { 0x000C, "Reserved" },
202 { 0x000D, "Reserved" },
203 { 0x000E, "Reserved" },
204 { 0x0010, "Resets all stored data in the IOD or IOC to its factory values" },
205 { 0x0011, "Resets all stored data in the IOD or IOC to its factory values" },
206 { 0x0012, "Reset and restore data" },
207 { 0x0013, "Reset and restore data" },
208 { 0x0014, "Reserved" },
209 { 0x0015, "Reserved" },
210 { 0x0016, "Reserved" },
214 #define PNDCP_OPTION_IP 0x01
215 #define PNDCP_OPTION_DEVICE 0x02
216 #define PNDCP_OPTION_DHCP 0x03
217 #define PNDCP_OPTION_RESERVED 0x04
218 #define PNDCP_OPTION_CONTROL 0x05
219 #define PNDCP_OPTION_DEVICEINITIATIVE 0x06
220 #define PNDCP_OPTION_TSN 0x07
221 #define PNDCP_OPTION_MANUF_X80 0x80
222 #define PNDCP_OPTION_MANUF_XFE 0xFE
223 #define PNDCP_OPTION_ALLSELECTOR 0xFF
225 static const range_string pn_dcp_option
[] = {
226 { 0x00, 0x00, "Reserved" },
227 { PNDCP_OPTION_IP
, PNDCP_OPTION_IP
, "IP" },
228 { PNDCP_OPTION_DEVICE
, PNDCP_OPTION_DEVICE
, "Device properties" },
229 { PNDCP_OPTION_DHCP
, PNDCP_OPTION_DHCP
, "DHCP" },
230 { PNDCP_OPTION_RESERVED
, PNDCP_OPTION_RESERVED
, "Reserved" },
231 { PNDCP_OPTION_CONTROL
, PNDCP_OPTION_CONTROL
, "Control" },
232 { PNDCP_OPTION_DEVICEINITIATIVE
, PNDCP_OPTION_DEVICEINITIATIVE
, "Device Initiative" },
233 { PNDCP_OPTION_TSN
, PNDCP_OPTION_TSN
, "TSN Domain"},
234 /*0x07 - 0x7F reserved */
235 /*0x80 - 0xFE manufacturer specific */
236 { PNDCP_OPTION_MANUF_X80
, PNDCP_OPTION_MANUF_XFE
, "Manufacturer specific" },
237 { PNDCP_OPTION_ALLSELECTOR
, PNDCP_OPTION_ALLSELECTOR
, "All Selector" },
241 #define PNDCP_SUBOPTION_IP_MAC 0x01
242 #define PNDCP_SUBOPTION_IP_IP 0x02
243 #define PNDCP_SUBOPTION_IP_FULL_IP_SUITE 0x03
245 static const value_string pn_dcp_suboption_ip
[] = {
246 { 0x00, "Reserved" },
247 { PNDCP_SUBOPTION_IP_MAC
, "MAC address" },
248 { PNDCP_SUBOPTION_IP_IP
, "IP parameter" },
249 { PNDCP_SUBOPTION_IP_FULL_IP_SUITE
, "Full IP suite" },
250 /*0x03 - 0xff reserved */
254 static const value_string pn_dcp_suboption_ip_block_info
[] = {
255 { 0x0000, "IP not set" },
256 { 0x0001, "IP set" },
257 { 0x0002, "IP set by DHCP" },
258 { 0x0080, "IP not set (address conflict detected)" },
259 { 0x0081, "IP set (address conflict detected)" },
260 { 0x0082, "IP set by DHCP (address conflict detected)" },
261 /*0x0003 - 0xffff reserved */
265 static const value_string pn_dcp_suboption_control_signal_value
[] = {
266 {0x0100, "Flash Once"},
270 #define PNDCP_SUBOPTION_DEVICE_MANUF 0x01
271 #define PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION 0x02
272 #define PNDCP_SUBOPTION_DEVICE_DEV_ID 0x03
273 #define PNDCP_SUBOPTION_DEVICE_DEV_ROLE 0x04
274 #define PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS 0x05
275 #define PNDCP_SUBOPTION_DEVICE_ALIAS_NAME 0x06
276 #define PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE 0x07
277 #define PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID 0x08
278 #define PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES 0x0A
280 static const value_string pn_dcp_suboption_device
[] = {
281 { 0x00, "Reserved" },
282 { PNDCP_SUBOPTION_DEVICE_MANUF
, "Manufacturer specific (Type of Station)" },
283 { PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION
, "Name of Station" },
284 { PNDCP_SUBOPTION_DEVICE_DEV_ID
, "Device ID" },
285 { PNDCP_SUBOPTION_DEVICE_DEV_ROLE
, "Device Role" },
286 { PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS
, "Device Options" },
287 { PNDCP_SUBOPTION_DEVICE_ALIAS_NAME
, "Alias Name" },
288 { PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE
, "Device Instance" },
289 { PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID
, "OEM Device ID"},
290 { PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES
,"RSI Properties" },
291 /*0x09 - 0xff reserved */
295 static const true_false_string pn_dcp_rsi_properties_value_bit
=
296 { "Available", "Not available" } ;
298 #define PNDCP_SUBOPTION_TSN_DOMAIN_NAME 0x01
299 #define PNDCP_SUBOPTION_TSN_NME_MANAGER 0x02
300 #define PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID 0x03
301 #define PNDCP_SUBOPTION_TSN_NME_AGENT 0x04
302 #define PNDCP_SUBOPTION_TSN_CIM_INTERFACE 0x05
304 static const value_string pn_dcp_suboption_tsn
[] = {
305 { 0x00, "Reserved" },
306 { PNDCP_SUBOPTION_TSN_DOMAIN_NAME
, "TSN Domain Name" },
307 { PNDCP_SUBOPTION_TSN_NME_MANAGER
, "NME Manager" },
308 { PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID
, "NME Paramater UUID" },
309 { PNDCP_SUBOPTION_TSN_NME_AGENT
, "NME Agent" },
310 { PNDCP_SUBOPTION_TSN_CIM_INTERFACE
, "CIM Interface" },
314 static const range_string pn_dcp_suboption_tsn_nme_prio
[] =
316 { 0x0000, 0x0000, "Highest priority NME manager" },
317 { 0x0001, 0x3000, "High priorities for NME manager" },
318 { 0x3001, 0x9FFF, "Low priorities for NME manager" },
319 { 0xA000, 0xA000, "Lowest priority for NME manager / Default priority for NME manager" },
320 { 0xA001, 0xFFFF, "Reserved" },
324 #define PNDCP_SUBOPTION_DHCP_CLIENT_ID 61
325 #define PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES 255
327 static const value_string pn_dcp_suboption_dhcp
[] = {
329 { 43, "Vendor specific" },
330 { 54, "Server identifier" },
331 { 55, "Parameter request list" },
332 { 60, "Class identifier" },
333 { PNDCP_SUBOPTION_DHCP_CLIENT_ID
, "DHCP client identifier" },
334 { 81, "FQDN, Fully Qualified Domain Name" },
335 { 97, "UUID/GUID-based Client" },
336 { PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES
, "Control DHCP for address resolution" },
337 /*all others reserved */
341 static const value_string pn_dcp_suboption_dhcp_control_parameter_data
[] = {
342 { 0x00, "Don't use DHCP (Default)" },
343 { 0x01, "Don't use DHCP, all DHCPOptions set to Reset to Factory value" },
344 { 0x02, "Use DHCP with the given set of DHCPOptions" },
348 #define PNDCP_SUBOPTION_CONTROL_START_TRANS 0x01
349 #define PNDCP_SUBOPTION_CONTROL_END_TRANS 0x02
350 #define PNDCP_SUBOPTION_CONTROL_SIGNAL 0x03
351 #define PNDCP_SUBOPTION_CONTROL_RESPONSE 0x04
352 #define PNDCP_SUBOPTION_CONTROL_FACT_RESET 0x05
353 #define PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT 0x06
355 static const value_string pn_dcp_suboption_control
[] = {
356 { 0x00, "Reserved" },
357 { PNDCP_SUBOPTION_CONTROL_START_TRANS
, "Start Transaction" },
358 { PNDCP_SUBOPTION_CONTROL_END_TRANS
, "End Transaction" },
359 { PNDCP_SUBOPTION_CONTROL_SIGNAL
, "Signal" },
360 { PNDCP_SUBOPTION_CONTROL_RESPONSE
, "Response" },
361 { PNDCP_SUBOPTION_CONTROL_FACT_RESET
, "Reset Factory Settings" },
362 { PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT
,"Reset to Factory" },
363 /*0x07 - 0xff reserved */
367 #define PNDCP_SUBOPTION_DEVICEINITIATIVE 0x01
369 static const value_string pn_dcp_suboption_deviceinitiative
[] = {
370 { 0x00, "Reserved" },
371 { PNDCP_SUBOPTION_DEVICEINITIATIVE
, "Device Initiative" },
372 /*0x00 - 0xff reserved */
376 static const value_string pn_dcp_deviceinitiative_value
[] = {
377 { 0x00, "Device does not issue a DCP-Hello-ReqPDU after power on" },
378 { 0x01, "Device does issue a DCP-Hello-ReqPDU after power on" },
379 /*0x02 - 0xff reserved */
383 static const value_string pn_dcp_suboption_all
[] = {
384 { 0xff, "ALL Selector" },
385 /* all other reserved */
389 static const value_string pn_dcp_suboption_other
[] = {
391 /* all other reserved */
395 static const value_string pn_dcp_suboption_manuf
[] = {
404 /* dissect the option field */
406 dissect_PNDCP_Option(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
407 proto_tree
*tree
, proto_item
*block_item
, int hfindex
, bool append_col
)
411 const value_string
*val_str
;
413 offset
= dissect_pn_uint8 (tvb
, offset
, pinfo
, tree
, hfindex
, &option
);
415 case PNDCP_OPTION_IP
:
416 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip
, &suboption
);
417 val_str
= pn_dcp_suboption_ip
;
419 case PNDCP_OPTION_DEVICE
:
420 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device
, &suboption
);
421 val_str
= pn_dcp_suboption_device
;
423 case PNDCP_OPTION_DHCP
:
424 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp
, &suboption
);
425 val_str
= pn_dcp_suboption_dhcp
;
427 case PNDCP_OPTION_CONTROL
:
428 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_control
, &suboption
);
429 val_str
= pn_dcp_suboption_control
;
431 case PNDCP_OPTION_DEVICEINITIATIVE
:
432 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_deviceinitiative
, &suboption
);
433 val_str
= pn_dcp_suboption_deviceinitiative
;
435 case PNDCP_OPTION_TSN
:
436 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn
, &suboption
);
437 val_str
= pn_dcp_suboption_tsn
;
439 case PNDCP_OPTION_ALLSELECTOR
:
440 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_all
, &suboption
);
441 val_str
= pn_dcp_suboption_all
;
444 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_manuf
, &suboption
);
445 val_str
= pn_dcp_suboption_manuf
;
448 proto_item_append_text(block_item
, ", Status from %s - %s",
449 rval_to_str_const(option
, pn_dcp_option
, "Unknown"),
450 val_to_str_const(suboption
, val_str
, "Unknown"));
453 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s", val_to_str_const(suboption
, val_str
, "Unknown"));
460 /* dissect the "IP" suboption */
462 dissect_PNDCP_Suboption_IP(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
463 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
464 uint8_t service_id
, bool is_response
)
467 uint16_t block_length
;
469 uint16_t block_qualifier
;
470 bool have_block_info
= false;
471 bool have_block_qualifier
= false;
474 proto_item
*item
= NULL
;
478 /* SuboptionIPParameter */
479 offset
= dissect_pn_uint8 (tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip
, &suboption
);
481 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
484 case PNDCP_SUBOPTION_IP_MAC
:
485 /* MACAddressValue? */
486 pn_append_info(pinfo
, dcp_item
, ", MAC");
487 proto_item_append_text(block_item
, "IP/MAC");
490 if (((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
491 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
492 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
493 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
494 have_block_info
= true;
498 /* BlockQualifier? */
499 if ((service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
500 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
501 have_block_qualifier
= true;
505 if (have_block_qualifier
) {
506 proto_item_append_text(block_item
, ", BlockQualifier: %s",
507 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
509 if (have_block_info
) {
510 proto_item_append_text(block_item
, ", BlockInfo: %s",
511 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
514 offset
= dissect_pn_mac(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_mac_address
, mac
);
515 set_address(&addr
, AT_ETHER
, 6, mac
);
516 proto_item_append_text(block_item
, ", MACAddress: %s", address_to_str(pinfo
->pool
, &addr
));
518 case PNDCP_SUBOPTION_IP_IP
:
519 pn_append_info(pinfo
, dcp_item
, ", IP");
520 proto_item_append_text(block_item
, "IP/IP");
523 if (((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
524 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
525 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
526 block_info
= tvb_get_ntohs(tvb
, offset
);
528 item
= proto_tree_add_uint(tree
, hf_pn_dcp_suboption_ip_block_info
, tvb
, offset
, 2, block_info
);
531 proto_item_append_text(block_item
, ", BlockInfo: %s",
532 val_to_str_const(block_info
, pn_dcp_suboption_ip_block_info
, "Undecoded"));
534 if (block_info
& 0x80) {
535 expert_add_info(pinfo
, item
, &ei_pn_dcp_ip_conflict
);
539 /* BlockQualifier? */
540 if ( (service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
541 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
542 proto_item_append_text(block_item
, ", BlockQualifier: %s",
543 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
547 /* IPParameterValue ... */
550 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_ip
, &ip
);
551 set_address(&addr
, AT_IPv4
, 4, &ip
);
552 proto_item_append_text(block_item
, ", IP: %s", address_to_str(pinfo
->pool
, &addr
));
555 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_subnetmask
, &ip
);
556 set_address(&addr
, AT_IPv4
, 4, &ip
);
557 proto_item_append_text(block_item
, ", Subnet: %s", address_to_str(pinfo
->pool
, &addr
));
559 /* StandardGateway */
560 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_standard_gateway
, &ip
);
561 set_address(&addr
, AT_IPv4
, 4, &ip
);
562 proto_item_append_text(block_item
, ", Gateway: %s", address_to_str(pinfo
->pool
, &addr
));
564 case PNDCP_SUBOPTION_IP_FULL_IP_SUITE
:
565 pn_append_info(pinfo
, dcp_item
, ", Full IP Suite");
566 proto_item_append_text(block_item
, "IP/Full IP Suite");
569 if (((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
570 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
571 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
572 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
573 have_block_info
= true;
577 /* BlockQualifier? */
578 if ((service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
579 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
580 have_block_qualifier
= true;
584 if (have_block_qualifier
) {
585 proto_item_append_text(block_item
, ", BlockQualifier: %s",
586 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
588 if (have_block_info
) {
589 proto_item_append_text(block_item
, ", BlockInfo: %s",
590 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
594 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_ip
, &ip
);
595 set_address(&addr
, AT_IPv4
, 4, &ip
);
596 proto_item_append_text(block_item
, ", IP: %s", address_to_str(pinfo
->pool
, &addr
));
599 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_subnetmask
, &ip
);
600 set_address(&addr
, AT_IPv4
, 4, &ip
);
601 proto_item_append_text(block_item
, ", Subnet: %s", address_to_str(pinfo
->pool
, &addr
));
603 /* StandardGateway */
604 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_standard_gateway
, &ip
);
605 set_address(&addr
, AT_IPv4
, 4, &ip
);
606 proto_item_append_text(block_item
, ", Gateway: %s", address_to_str(pinfo
->pool
, &addr
));
609 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_ip
, &ip
);
610 set_address(&addr
, AT_IPv4
, 4, &ip
);
611 proto_item_append_text(block_item
, ", DNSServerIP1: %s", address_to_str(pinfo
->pool
, &addr
));
614 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_subnetmask
, &ip
);
615 set_address(&addr
, AT_IPv4
, 4, &ip
);
616 proto_item_append_text(block_item
, ", DNSServerIP2: %s", address_to_str(pinfo
->pool
, &addr
));
619 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_standard_gateway
, &ip
);
620 set_address(&addr
, AT_IPv4
, 4, &ip
);
621 proto_item_append_text(block_item
, ", DNSServerIP3: %s", address_to_str(pinfo
->pool
, &addr
));
624 offset
= dissect_pn_ipv4(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_ip_standard_gateway
, &ip
);
625 set_address(&addr
, AT_IPv4
, 4, &ip
);
626 proto_item_append_text(block_item
, ", DNSServerIP4: %s", address_to_str(pinfo
->pool
, &addr
));
630 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
637 /* dissect the "device" suboption */
639 dissect_PNDCP_Suboption_Device(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
640 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
641 uint8_t service_id
, bool is_response
)
644 uint16_t block_length
;
652 uint16_t block_info
= 0;
653 uint16_t block_qualifier
= 0;
654 bool have_block_info
= false;
655 bool have_block_qualifier
= false;
656 uint8_t device_instance_high
;
657 uint8_t device_instance_low
;
658 uint16_t oem_vendor_id
;
659 uint16_t oem_device_id
;
660 proto_item
*sub_item
;
661 proto_tree
*sub_tree
;
662 conversation_t
*conversation
;
663 stationInfo
*station_info
;
665 /* SuboptionDevice... */
666 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device
, &suboption
);
668 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
671 if ( ((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
672 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
673 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
674 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
675 have_block_info
= true;
679 /* BlockQualifier? */
680 if ( (service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
681 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
682 have_block_qualifier
= true;
687 case PNDCP_SUBOPTION_DEVICE_MANUF
:
689 * XXX - IEC 61158-6-10 Edition 4.0, section 4.3, says this field
690 * "shall be coded as data type VisibleString", and that VisibleString
691 * is "ISO/IEC 646 - International Reference Version without the "del"
692 * (coding 0x7F) character", i.e. ASCII.
694 * However, at least one capture has a packet where 0xAE is used in
695 * a place where a registered trademark symbol would be appropriate,
696 * so the host sending it apparently extended ASCII to ISO 8859-n
697 * for some value of n. That may have just been an error on their
698 * part, not realizing that they should have done "(R)" or something
701 proto_tree_add_item_ret_display_string (tree
, hf_pn_dcp_suboption_device_typeofstation
, tvb
, offset
, block_length
, ENC_ASCII
, pinfo
->pool
, &typeofstation
);
702 pn_append_info(pinfo
, dcp_item
, ", DeviceVendorValue");
703 proto_item_append_text(block_item
, "Device/Manufacturer specific");
704 if (have_block_qualifier
) {
705 proto_item_append_text(block_item
, ", BlockQualifier: %s",
706 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
708 if (have_block_info
){
709 proto_item_append_text(block_item
, ", BlockInfo: %s",
710 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
712 proto_item_append_text(block_item
, ", DeviceVendorValue: \"%s\"", typeofstation
);
715 if (PINFO_FD_VISITED(pinfo
) == false) {
716 /* Create a conversation between the MAC addresses */
717 conversation
= find_conversation(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
718 if (conversation
== NULL
) {
719 /* Create new conversation, need to switch dl_src & dl_dst if not a response
720 * All conversations are based on Device MAC as addr1 */
722 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
725 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_dst
, &pinfo
->dl_src
, CONVERSATION_NONE
, 0, 0, 0);
729 station_info
= (stationInfo
*)conversation_get_proto_data(conversation
, proto_pn_dcp
);
730 if (station_info
== NULL
) {
731 station_info
= wmem_new0(wmem_file_scope(), stationInfo
);
732 init_pnio_rtc1_station(station_info
);
733 conversation_add_proto_data(conversation
, proto_pn_dcp
, station_info
);
736 station_info
->typeofstation
= wmem_strdup(wmem_file_scope(), typeofstation
);
739 offset
+= block_length
;
742 case PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION
:
744 * XXX - IEC 61158-6-10 Edition 4.0 says, in section 4.3.1.4.15
745 * "Coding of the field NameOfStationValue", that "This field shall
746 * be coded as data type OctetString with 1 to 240 octets. The
747 * definition of IETF RFC 5890 and the following syntax applies: ..."
749 * RFC 5890 means Punycode; should we translate the domain name to
750 * UTF-8 and show both the untranslated and translated domain name?
752 * They don't mention anything about the RFC 1035 encoding of
753 * domain names as mentioned in section 3.1 "Name space definitions",
754 * with the labels being counted strings; does that mean that this
755 * is just an ASCII string to be interpreted as a Punycode Unicode
758 proto_tree_add_item_ret_display_string (tree
, hf_pn_dcp_suboption_device_nameofstation
, tvb
, offset
, block_length
, ENC_ASCII
, pinfo
->pool
, &nameofstation
);
759 pn_append_info(pinfo
, dcp_item
, wmem_strdup_printf(pinfo
->pool
, ", NameOfStation:\"%s\"", nameofstation
));
760 proto_item_append_text(block_item
, "Device/NameOfStation");
761 if (have_block_qualifier
) {
762 proto_item_append_text(block_item
, ", BlockQualifier: %s",
763 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
765 if (have_block_info
) {
766 proto_item_append_text(block_item
, ", BlockInfo: %s",
767 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
769 proto_item_append_text(block_item
, ", \"%s\"", nameofstation
);
772 if (PINFO_FD_VISITED(pinfo
) == false) {
773 /* Create a conversation between the MAC addresses */
774 conversation
= find_conversation(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
775 if (conversation
== NULL
) {
776 /* Create new conversation, need to switch dl_src & dl_dst if not a response
777 * All conversations are based on Device MAC as addr1 */
779 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
782 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_dst
, &pinfo
->dl_src
, CONVERSATION_NONE
, 0, 0, 0);
786 station_info
= (stationInfo
*)conversation_get_proto_data(conversation
, proto_pn_dcp
);
787 if (station_info
== NULL
) {
788 station_info
= wmem_new0(wmem_file_scope(), stationInfo
);
789 init_pnio_rtc1_station(station_info
);
790 conversation_add_proto_data(conversation
, proto_pn_dcp
, station_info
);
793 station_info
->nameofstation
= wmem_strdup(wmem_file_scope(), nameofstation
);
796 offset
+= block_length
;
799 case PNDCP_SUBOPTION_DEVICE_DEV_ID
:
800 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_vendor_id
, &vendor_id
);
801 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_id
, &device_id
);
803 if (PINFO_FD_VISITED(pinfo
) == false) {
804 /* Create a conversation between the MAC addresses */
805 conversation
= find_conversation(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
806 if (conversation
== NULL
) {
807 /* Create new conversation, need to switch dl_src & dl_dst if not a response
808 * All conversations are based on Device MAC as addr1 */
810 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
813 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_dst
, &pinfo
->dl_src
, CONVERSATION_NONE
, 0, 0, 0);
817 station_info
= (stationInfo
*)conversation_get_proto_data(conversation
, proto_pn_dcp
);
818 if (station_info
== NULL
) {
819 station_info
= wmem_new0(wmem_file_scope(), stationInfo
);
820 init_pnio_rtc1_station(station_info
);
821 conversation_add_proto_data(conversation
, proto_pn_dcp
, station_info
);
824 station_info
->u16Vendor_id
= vendor_id
;
825 station_info
->u16Device_id
= device_id
;
829 pn_append_info(pinfo
, dcp_item
, ", Dev-ID");
830 proto_item_append_text(block_item
, "Device/Device ID");
831 if (have_block_qualifier
) {
832 proto_item_append_text(block_item
, ", BlockQualifier: %s",
833 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
835 if (have_block_info
) {
836 proto_item_append_text(block_item
, ", BlockInfo: %s",
837 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
839 proto_item_append_text(block_item
, ", VendorID: 0x%04x / DeviceID: 0x%04x", vendor_id
, device_id
);
841 case PNDCP_SUBOPTION_DEVICE_DEV_ROLE
:
842 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_role
, &device_role
);
843 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_reserved8
, NULL
);
844 pn_append_info(pinfo
, dcp_item
, ", Dev-Role");
845 proto_item_append_text(block_item
, "Device/Device Role");
846 if (have_block_qualifier
) {
847 proto_item_append_text(block_item
, ", BlockQualifier: %s",
848 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
851 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
852 if (device_role
& 0x01)
853 proto_item_append_text(block_item
, ", IO-Device");
854 if (device_role
& 0x02)
855 proto_item_append_text(block_item
, ", IO-Controller");
856 if (device_role
& 0x04)
857 proto_item_append_text(block_item
, ", IO-Multidevice");
858 if (device_role
& 0x08)
859 proto_item_append_text(block_item
, ", PN-Supervisor");
861 case PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS
:
862 info_str
= wmem_strdup_printf(pinfo
->pool
, ", Dev-Options(%u)", block_length
/2);
863 pn_append_info(pinfo
, dcp_item
, info_str
);
864 proto_item_append_text(block_item
, "Device/Device Options");
865 if (have_block_qualifier
) {
866 proto_item_append_text(block_item
, ", BlockQualifier: %s",
867 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
869 if (have_block_info
) {
870 proto_item_append_text(block_item
, ", BlockInfo: %s",
871 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
873 proto_item_append_text(block_item
, ", %u options", block_length
/2);
874 for( ; block_length
!= 0; block_length
-= 2) {
875 offset
= dissect_PNDCP_Option(tvb
, offset
, pinfo
, tree
, NULL
/*block_item*/, hf_pn_dcp_option
,
876 false /* append_col */);
879 case PNDCP_SUBOPTION_DEVICE_ALIAS_NAME
:
881 * XXX - IEC 61158-6-10 Edition 4.0, section 4.3.1.4.17 "Coding of
882 * the field AliasNameValue", says this field "shall be coded as
883 * OctetString. The content shall be the concatenation of the content
884 * of the fields NameOfPort and NameOfStation.
886 * AliasNameValue = NameOfPort + "." + NameOfStation
890 * It says in section 4.3.1.4.16 "Coding of the field NameOfPort"
891 * that "This field shall be coded as OctetString[8] or
892 * OctetString[14] as "port-xyz" or "port-xyz-rstuv" where x, y,
893 * z is in the range "0"-"9" from 001 up to 255 and r, s, t, u, v
894 * is in the range "0"-"9" from 00000 up to 65535. ...
895 * Furthermore, the definition of IETF RFC 5890 shall be applied."
897 * That suggests that the Octets are probably just ASCII characters;
898 * IETF RFC 5890 means Punycode, but there isn't anything in those
899 * string formats that requires non-ASCII characters - they're
900 * just literally "port-" followed by numbers and hyphens.
902 * It says in section 4.3.1.4.15 "Coding of the field
903 * NameOfStationValue" that it's a domain name, complete with
906 proto_tree_add_item_ret_display_string (tree
, hf_pn_dcp_suboption_device_aliasname
, tvb
, offset
, block_length
, ENC_ASCII
, pinfo
->pool
, &aliasname
);
907 pn_append_info(pinfo
, dcp_item
, wmem_strdup_printf(pinfo
->pool
, ", AliasName:\"%s\"", aliasname
));
908 proto_item_append_text(block_item
, "Device/AliasName");
909 if (have_block_qualifier
) {
910 proto_item_append_text(block_item
, ", BlockQualifier: %s",
911 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
913 if (have_block_info
) {
914 proto_item_append_text(block_item
, ", BlockInfo: %s",
915 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
917 proto_item_append_text(block_item
, ", \"%s\"", aliasname
);
918 offset
+= block_length
;
920 case PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE
:
921 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_instance_high
, &device_instance_high
);
922 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_instance_low
, &device_instance_low
);
923 pn_append_info(pinfo
, dcp_item
, ", Dev-Instance");
924 proto_item_append_text(block_item
, "Device/Device Instance");
925 if (have_block_qualifier
) {
926 proto_item_append_text(block_item
, ", BlockQualifier: %s",
927 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
929 if (have_block_info
) {
930 proto_item_append_text(block_item
, ", BlockInfo: %s",
931 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
933 proto_item_append_text(block_item
, ", InstanceHigh: %d, Instance Low: %d",
934 device_instance_high
, device_instance_low
);
936 case PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID
:
937 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_oem_ven_id
, &oem_vendor_id
);
938 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_device_oem_dev_id
, &oem_device_id
);
939 pn_append_info(pinfo
, dcp_item
, ", OEM-Dev-ID");
940 proto_item_append_text(block_item
, "Device/OEM Device ID");
941 if(have_block_qualifier
) {
942 proto_item_append_text(block_item
, ", BlockQualifier: %s",
943 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
945 if(have_block_info
) {
946 proto_item_append_text(block_item
, ", BlockInfo: %s",
947 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
949 proto_item_append_text(block_item
, ", OEMVendorID: 0x%04x / OEMDeviceID: 0x%04x", oem_vendor_id
, oem_device_id
);
951 case PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES
:
952 sub_item
= proto_tree_add_item(tree
, hf_pn_dcp_rsi_properties_value
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
953 sub_tree
= proto_item_add_subtree(sub_item
, ett_pn_dcp_rsi_properties_value
);
955 static int* const flags
[] = {
956 &hf_pn_dcp_rsi_properties_value_bit0
,
957 &hf_pn_dcp_rsi_properties_value_bit1
,
958 &hf_pn_dcp_rsi_properties_value_bit2
,
959 &hf_pn_dcp_rsi_properties_value_bit3
,
960 &hf_pn_dcp_rsi_properties_value_bit4
,
961 &hf_pn_dcp_rsi_properties_value_bit5
,
962 &hf_pn_dcp_rsi_properties_value_otherbits
,
966 proto_tree_add_bitmask(sub_tree
, tvb
, offset
, hf_pn_dcp_rsi_properties_value
, ett_pn_dcp_rsi_properties_value
, flags
, ENC_BIG_ENDIAN
);
970 if (pinfo
->fd
->visited
== false) {
971 /* Create a conversation between the MAC addresses */
972 conversation
= find_conversation(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
973 if (conversation
== NULL
) {
974 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
977 station_info
= (stationInfo
*)conversation_get_proto_data(conversation
, proto_pn_dcp
);
978 if (station_info
== NULL
) {
979 station_info
= wmem_new0(wmem_file_scope(), stationInfo
);
980 init_pnio_rtc1_station(station_info
);
981 conversation_add_proto_data(conversation
, proto_pn_dcp
, station_info
);
985 pn_append_info(pinfo
, dcp_item
, ", RSI-Properties");
986 proto_item_append_text(block_item
, "Device/RSI Properties");
987 if (have_block_qualifier
) {
988 proto_item_append_text(block_item
, ", BlockQualifier: %s",
989 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
991 if (have_block_info
) {
992 proto_item_append_text(block_item
, ", BlockInfo: %s",
993 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
997 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
1003 /* dissect the "tsn" suboption */
1005 dissect_PNDCP_Suboption_TSN(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
,
1006 proto_tree
* tree
, proto_item
* block_item
, proto_item
* dcp_item
,
1007 uint8_t service_id
, bool is_response
)
1010 uint16_t block_length
;
1013 e_guid_t tsn_domain_uuid
;
1014 e_guid_t nme_parameter_uuid
;
1015 e_guid_t nme_name_uuid
;
1018 uint16_t block_info
= 0;
1019 uint16_t block_qualifier
= 0;
1020 bool have_block_info
= false;
1021 bool have_block_qualifier
= false;
1022 uint8_t instance_id_high
;
1023 uint8_t instance_id_low
;
1024 conversation_t
* conversation
;
1025 stationInfo
* station_info
;
1026 bool is_zeros
= true;
1028 /* SuboptionTSN... */
1029 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn
, &suboption
);
1031 /* DCPBlockLength */
1032 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1035 if (((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
1036 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
1037 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
1038 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
1039 have_block_info
= true;
1043 /* BlockQualifier? */
1044 if ((service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
1045 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1046 have_block_qualifier
= true;
1050 switch (suboption
) {
1051 case PNDCP_SUBOPTION_TSN_DOMAIN_NAME
:
1053 offset
= dissect_pn_uuid(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn_domain_uuid
, &tsn_domain_uuid
);
1054 proto_tree_add_item_ret_display_string(tree
, hf_pn_dcp_suboption_tsn_domain_name
, tvb
, offset
, (block_length
-16), ENC_ASCII
| ENC_NA
, pinfo
->pool
, &domain_name
);
1056 pn_append_info(pinfo
, dcp_item
, ", TSN-Domain Name");
1057 proto_item_append_text(block_item
, "TSN/TSN-Domain Name");
1058 if (have_block_qualifier
) {
1059 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1060 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1062 if (have_block_info
)
1063 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1065 pn_append_info(pinfo
, dcp_item
, wmem_strdup_printf(pinfo
->pool
, ", DomainName:\"%s\"", domain_name
));
1066 proto_item_append_text(block_item
, ", \"%s\"", domain_name
);
1067 offset
+= (block_length
-16);
1070 for (int i
= 0; i
< 8; i
++)
1072 if (tsn_domain_uuid
.data4
[i
] != 0)
1079 if ((tsn_domain_uuid
.data1
== 0) && (tsn_domain_uuid
.data2
== 0) && (tsn_domain_uuid
.data3
== 0) && (is_zeros
))
1080 proto_item_append_text(block_item
, ", No TSN domain assigned");
1082 proto_item_append_text(block_item
, ", UUID identifying a TSN domain using SNMP/ LLDP/ DCP");
1086 case PNDCP_SUBOPTION_TSN_NME_MANAGER
:
1088 pn_append_info(pinfo
, dcp_item
, ", NME-Manager");
1089 proto_item_append_text(block_item
, "TSN/NME-Manager");
1091 if (have_block_qualifier
)
1093 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1094 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1097 if (have_block_info
)
1099 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn_nme_prio
, &nme_prio
);
1100 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1102 if (nme_prio
== 0x0000)
1103 proto_item_append_text(block_item
, ", Highest priority NME manager");
1104 else if ((0x0001 <= nme_prio
) && (nme_prio
<= 0x3000))
1105 proto_item_append_text(block_item
, ", High priorities for NME manager");
1106 else if ((0x3001 <= nme_prio
) && (nme_prio
<= 0x9FFF))
1107 proto_item_append_text(block_item
, ", Low priorities for NME manager");
1108 else if (0xA000 == nme_prio
)
1109 proto_item_append_text(block_item
, ", Lowest priority for NME manager / Default priority for NME manager");
1111 proto_item_append_text(block_item
, ", Reserved");
1116 case PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID
:
1118 pn_append_info(pinfo
, dcp_item
, ", NME-Parameter UUID");
1119 proto_item_append_text(block_item
, "TSN/NME-Parameter UUID");
1121 if (block_length
> 0)
1123 offset
= dissect_pn_uuid(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn_nme_parameter_uuid
, &nme_parameter_uuid
);
1125 if (have_block_qualifier
)
1127 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1128 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1130 if (have_block_info
)
1131 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1135 for (int i
= 0; i
< 8; i
++)
1137 if (nme_parameter_uuid
.data4
[i
] != 0)
1143 if ((nme_parameter_uuid
.data1
== 0) && (nme_parameter_uuid
.data2
== 0) && (nme_parameter_uuid
.data3
== 0) && (is_zeros
))
1144 proto_item_append_text(block_item
, ", Unconfigured");
1146 proto_item_append_text(block_item
, ", UUID identifying an NME parameter set within the TSN domain.");
1150 case PNDCP_SUBOPTION_TSN_NME_AGENT
:
1152 pn_append_info(pinfo
, dcp_item
, ", NME-Agent");
1153 proto_item_append_text(block_item
, "TSN/NME-Agent");
1155 if (have_block_qualifier
)
1157 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1158 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1161 if (have_block_info
)
1163 offset
= dissect_pn_uuid(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_tsn_nme_agent
, &nme_name_uuid
);
1164 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1167 for (int i
= 0; i
< 8; i
++)
1169 if (nme_name_uuid
.data4
[i
] != 0)
1176 if ((nme_name_uuid
.data1
== 0) && (nme_name_uuid
.data2
== 0) && (nme_name_uuid
.data3
== 0) && (is_zeros
))
1177 proto_item_append_text(block_item
, ", No NME assigned");
1179 proto_item_append_text(block_item
, ", UUID identifying an NME using SNMP / LLDP / DCP");
1183 case PNDCP_SUBOPTION_TSN_CIM_INTERFACE
:
1185 pn_append_info(pinfo
, dcp_item
, ", CIM-Interface");
1186 proto_item_append_text(block_item
, "TSN/CIM-Interface");
1188 if (have_block_qualifier
)
1190 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1191 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1193 if (have_block_info
)
1196 dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_vendor_id_high
, &vendor_id
);
1197 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_vendor_id_low
, &vendor_id
);
1199 dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_device_id_high
, &device_id
);
1200 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_device_id_low
, &device_id
);
1202 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_instance_id_high
, &instance_id_high
);
1203 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_instance_id_low
, &instance_id_low
);
1205 if (pinfo
->fd
->visited
== false) {
1206 /* Create a conversation between the MAC addresses */
1207 conversation
= find_conversation(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
1208 if (conversation
== NULL
) {
1209 conversation
= conversation_new(pinfo
->num
, &pinfo
->dl_src
, &pinfo
->dl_dst
, CONVERSATION_NONE
, 0, 0, 0);
1212 station_info
= (stationInfo
*)conversation_get_proto_data(conversation
, proto_pn_dcp
);
1213 if (station_info
== NULL
) {
1214 station_info
= wmem_new0(wmem_file_scope(), stationInfo
);
1215 init_pnio_rtc1_station(station_info
);
1216 conversation_add_proto_data(conversation
, proto_pn_dcp
, station_info
);
1219 station_info
->u16Vendor_id
= vendor_id
;
1220 station_info
->u16Device_id
= device_id
;
1223 proto_item_append_text(block_item
, ", BlockInfo: %s", rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1225 proto_item_append_text(block_item
, ", VendorID: 0x%04x / DeviceID: 0x%04x / InstanceIDHigh: 0x%04x / InstanceIDLow: 0x%04x", vendor_id
, device_id
, instance_id_high
, instance_id_low
);
1230 pn_append_info(pinfo
, dcp_item
, ", TSN/Reserved");
1231 proto_item_append_text(block_item
, "TSN/Reserved");
1237 /* dissect the "DHCP" suboption */
1239 dissect_PNDCP_Suboption_DHCP(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1240 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
1241 uint8_t service_id _U_
, bool is_response _U_
)
1244 uint8_t option_code
= 0;
1245 uint16_t block_length
;
1246 uint16_t block_info
= 0;
1247 uint16_t block_qualifier
= 0;
1248 uint8_t dhcpparameterlength
= 0;
1249 uint8_t dhcpparameterdata
= 0;
1250 uint8_t dhcpcontrolparameterdata
= 0;
1251 bool have_block_info
= false;
1252 bool have_block_qualifier
= false;
1253 int expected_offset
;
1256 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp
, &suboption
);
1257 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1259 expected_offset
= offset
+ block_length
;
1262 if ( ((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
1263 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
1264 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
1265 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
1266 have_block_info
=true;
1269 /* BlockQualifier? */
1270 if ( (service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
1271 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1272 have_block_qualifier
=true;
1276 switch (suboption
) {
1277 case PNDCP_SUBOPTION_DHCP_CLIENT_ID
:
1278 pn_append_info(pinfo
, dcp_item
, ", DHCP client identifier");
1279 proto_item_append_text(block_item
, "DHCP/Client-ID");
1280 if (have_block_qualifier
) {
1281 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1282 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1284 if (have_block_info
) {
1285 proto_item_append_text(block_item
, ", BlockInfo: %s",
1286 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1288 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_option_code
, &option_code
);
1289 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_parameter_length
, &dhcpparameterlength
);
1290 if (dhcpparameterlength
> 0) {
1291 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_parameter_data
, &dhcpparameterdata
);
1292 if (dhcpparameterlength
== 1) {
1293 if (dhcpparameterdata
== 1) {
1294 proto_item_append_text(block_item
, ", Client-ID: MAC Address");
1297 proto_item_append_text(block_item
, ", Client-ID: Name of Station");
1301 proto_item_append_text(block_item
, ", Client-ID: Arbitrary");
1303 * XXX - IEC 61158-6-10 Edition 4.0, section 4.3.1.4.21.5
1304 * "Use of arbitrary client identifier", that this is an
1305 * OctetString to be used as a client identifier with DHCP.
1307 * Does that mean it should be FT_BYTES, possibly with
1308 * the BASE_SHOW_ASCII_PRINTABLE flag to show it as ASCII
1309 * iff it's printable? Or should packet-dhcp.c export
1310 * dissect_dhcpopt_client_identifier(), so that we can
1311 * use its heuristics?
1313 proto_tree_add_item(tree
, hf_pn_dcp_suboption_dhcp_arbitrary_client_id
, tvb
, offset
, dhcpparameterlength
- 1, ENC_ASCII
);
1314 offset
+= (dhcpparameterlength
-1);
1318 case PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES
:
1319 pn_append_info(pinfo
, dcp_item
, ", Control DHCP for address resolution");
1320 proto_item_append_text(block_item
, "DHCP/Control DHCP for address resolution");
1321 if (have_block_qualifier
) {
1322 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1323 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1325 if (have_block_info
) {
1326 proto_item_append_text(block_item
, ", BlockInfo: %s",
1327 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1329 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_option_code
, &option_code
);
1330 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_parameter_length
, &dhcpparameterlength
);
1331 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_dhcp_control_parameter_data
, &dhcpcontrolparameterdata
);
1334 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
1337 if (expected_offset
> offset
) {
1338 offset
= dissect_pn_user_data(tvb
, offset
, pinfo
, tree
, expected_offset
- offset
, "Undefined");
1345 /* dissect the "control" suboption */
1347 dissect_PNDCP_Suboption_Control(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1348 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
1349 uint8_t service_id _U_
, bool is_response _U_
)
1352 uint16_t block_length
;
1353 uint16_t block_qualifier
;
1354 uint16_t BlockQualifier
;
1355 uint16_t u16SignalValue
;
1357 uint8_t block_error
;
1358 proto_item
*item
= NULL
;
1361 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_control
, &suboption
);
1362 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1364 if (service_id
== PNDCP_SERVICE_ID_SET
&& block_length
== 0) {
1365 pn_append_info(pinfo
, dcp_item
, ", Erroneous DCPSet block");
1366 proto_item_append_text(block_item
, "Control/Erroneous DCPSet block");
1369 switch (suboption
) {
1370 case PNDCP_SUBOPTION_CONTROL_START_TRANS
:
1371 pn_append_info(pinfo
, dcp_item
, ", Start-Trans");
1372 proto_item_append_text(block_item
, "Control/Start-Transaction");
1373 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1375 case PNDCP_SUBOPTION_CONTROL_END_TRANS
:
1376 pn_append_info(pinfo
, dcp_item
, ", End-Trans");
1377 proto_item_append_text(block_item
, "Control/End-Transaction");
1378 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1380 case PNDCP_SUBOPTION_CONTROL_SIGNAL
:
1381 pn_append_info(pinfo
, dcp_item
, ", Signal");
1382 proto_item_append_text(block_item
, "Control/Signal");
1383 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1386 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_control_signal_value
, &u16SignalValue
);
1388 case PNDCP_SUBOPTION_CONTROL_RESPONSE
:
1389 proto_item_append_text(block_item
, "Control/Response");
1390 offset
= dissect_PNDCP_Option(tvb
, offset
, pinfo
, tree
, block_item
, hf_pn_dcp_suboption_control_option
,
1391 false /* append_col */);
1392 block_error
= tvb_get_uint8(tvb
, offset
);
1394 item
= proto_tree_add_uint(tree
, hf_pn_dcp_block_error
, tvb
, offset
, 1, block_error
);
1397 if (block_error
!= 0) {
1398 expert_add_info_format(pinfo
, item
, &ei_pn_dcp_block_error_unknown
, "%s",
1399 val_to_str_const(block_error
, pn_dcp_block_error
, "Unknown"));
1401 info_str
= wmem_strdup_printf(pinfo
->pool
, ", Response(%s)",
1402 val_to_str_const(block_error
, pn_dcp_block_error
, "Unknown"));
1403 pn_append_info(pinfo
, dcp_item
, info_str
);
1404 proto_item_append_text(block_item
, ", BlockError: %s",
1405 val_to_str_const(block_error
, pn_dcp_block_error
, "Unknown"));
1408 case PNDCP_SUBOPTION_CONTROL_FACT_RESET
:
1409 pn_append_info(pinfo
, dcp_item
, ", Reset FactorySettings");
1410 proto_item_append_text(block_item
, "Control/Reset FactorySettings");
1412 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_blockqualifier
, &BlockQualifier
);
1413 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1414 val_to_str_const(BlockQualifier
, pn_dcp_suboption_other
, "reserved"));
1418 case PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT
:
1419 pn_append_info(pinfo
, dcp_item
, ", Reset to Factory");
1420 proto_item_append_text(block_item
, "Reset to FactorySettings");
1422 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_blockqualifier_r2f
, &BlockQualifier
);
1423 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1424 val_to_str_const(BlockQualifier
, pn_dcp_BlockQualifier
, "reserved"));
1429 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
1437 /* dissect the "deviceinitiative" suboption */
1439 dissect_PNDCP_Suboption_DeviceInitiative(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1440 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
1441 uint8_t service_id
, bool is_response
)
1444 uint16_t block_length
;
1445 uint16_t block_info
;
1446 uint16_t block_qualifier
;
1450 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_deviceinitiative
, &suboption
);
1451 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1453 pn_append_info(pinfo
, dcp_item
, ", DeviceInitiative");
1454 proto_item_append_text(block_item
, "DeviceInitiative/DeviceInitiative");
1457 if ( ((service_id
== PNDCP_SERVICE_ID_IDENTIFY
) && is_response
) ||
1458 ((service_id
== PNDCP_SERVICE_ID_HELLO
) && !is_response
) ||
1459 ((service_id
== PNDCP_SERVICE_ID_GET
) && is_response
)) {
1460 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_info
, &block_info
);
1461 proto_item_append_text(block_item
, ", BlockInfo: %s",
1462 rval_to_str_const(block_info
, pn_dcp_block_info
, "Unknown"));
1466 /* BlockQualifier? */
1467 if ( (service_id
== PNDCP_SERVICE_ID_SET
) && !is_response
) {
1468 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_qualifier
, &block_qualifier
);
1469 proto_item_append_text(block_item
, ", BlockQualifier: %s",
1470 val_to_str_const(block_qualifier
, pn_dcp_block_qualifier
, "Unknown"));
1474 /* DeviceInitiativeValue */
1475 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_deviceinitiative_value
, &value
);
1481 /* dissect the "all" suboption */
1483 dissect_PNDCP_Suboption_All(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1484 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
1485 uint8_t service_id _U_
, bool is_response _U_
)
1488 uint16_t block_length
;
1491 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_all
, &suboption
);
1492 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1494 switch (suboption
) {
1496 pn_append_info(pinfo
, dcp_item
, ", All");
1497 proto_item_append_text(block_item
, "All/All");
1500 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
1507 /* dissect the "manufacturer" suboption */
1509 dissect_PNDCP_Suboption_Manuf(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1510 proto_tree
*tree
, proto_item
*block_item
, proto_item
*dcp_item
,
1511 uint8_t service_id _U_
, bool is_response _U_
)
1513 uint16_t block_length
;
1515 offset
= dissect_pn_uint8( tvb
, offset
, pinfo
, tree
, hf_pn_dcp_suboption_manuf
, NULL
);
1517 pn_append_info(pinfo
, dcp_item
, ", Manufacturer Specific");
1518 proto_item_append_text(block_item
, "Manufacturer Specific");
1520 if (tvb_reported_length_remaining(tvb
, offset
)>0)
1522 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_block_length
, &block_length
);
1523 offset
= dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, block_length
);
1529 /* dissect one DCP block */
1531 dissect_PNDCP_Block(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1532 proto_tree
*tree
, proto_item
*dcp_item
,
1533 uint8_t service_id
, bool is_response
)
1536 proto_item
*block_item
;
1537 proto_tree
*block_tree
;
1538 int ori_offset
= offset
;
1540 /* subtree for block */
1541 block_item
= proto_tree_add_none_format(tree
, hf_pn_dcp_block
,
1542 tvb
, offset
, 0, "Block: ");
1543 block_tree
= proto_item_add_subtree(block_item
, ett_pn_dcp_block
);
1546 offset
= dissect_pn_uint8(tvb
, offset
, pinfo
, block_tree
, hf_pn_dcp_option
, &option
);
1548 if (option
== PNDCP_OPTION_IP
)
1550 offset
= dissect_PNDCP_Suboption_IP(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1552 else if (option
== PNDCP_OPTION_DEVICE
)
1554 offset
= dissect_PNDCP_Suboption_Device(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1556 else if (option
== PNDCP_OPTION_DHCP
)
1558 offset
= dissect_PNDCP_Suboption_DHCP(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1560 else if (option
== PNDCP_OPTION_CONTROL
)
1562 offset
= dissect_PNDCP_Suboption_Control(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1564 else if (option
== PNDCP_OPTION_DEVICEINITIATIVE
)
1566 offset
= dissect_PNDCP_Suboption_DeviceInitiative(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1568 else if (option
== PNDCP_OPTION_TSN
)
1570 offset
= dissect_PNDCP_Suboption_TSN(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1572 else if (option
== PNDCP_OPTION_ALLSELECTOR
)
1574 offset
= dissect_PNDCP_Suboption_All(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1576 else if (PNDCP_OPTION_MANUF_X80
<= option
&& option
<= PNDCP_OPTION_MANUF_XFE
)
1578 offset
= dissect_PNDCP_Suboption_Manuf(tvb
, offset
, pinfo
, block_tree
, block_item
, dcp_item
, service_id
, is_response
);
1582 pn_append_info(pinfo
, dcp_item
, ", Reserved");
1583 proto_item_append_text(block_item
, "Reserved");
1584 /* there isn't a predefined suboption type for reserved option, rest of the block will be seen as padding */
1587 proto_item_set_len(block_item
, offset
-ori_offset
);
1589 if (((offset
-ori_offset
) & 1) && (tvb_reported_length_remaining(tvb
, offset
) > 0)) {
1590 /* we have an odd number of bytes in this block, add a padding byte */
1591 offset
= dissect_pn_padding(tvb
, offset
, pinfo
, tree
, 1);
1598 /* dissect a whole DCP PDU */
1600 dissect_PNDCP_PDU(tvbuff_t
*tvb
,
1601 packet_info
*pinfo
, proto_tree
*tree
, proto_item
*dcp_item
)
1604 uint8_t service_type
;
1606 uint16_t response_delay
;
1607 uint16_t data_length
;
1610 bool is_response
= false;
1613 offset
= dissect_pn_uint8 (tvb
, offset
, pinfo
, tree
, hf_pn_dcp_service_id
, &service_id
);
1614 offset
= dissect_pn_uint8 (tvb
, offset
, pinfo
, tree
, hf_pn_dcp_service_type
, &service_type
);
1615 proto_tree_add_item_ret_uint(tree
, hf_pn_dcp_xid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &xid
);
1617 if (service_id
== PNDCP_SERVICE_ID_IDENTIFY
&& service_type
== PNDCP_SERVICE_TYPE_REQUEST
) {
1618 /* multicast header */
1619 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_response_delay
, &response_delay
);
1621 /* unicast header */
1622 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_reserved16
, NULL
);
1624 offset
= dissect_pn_uint16(tvb
, offset
, pinfo
, tree
, hf_pn_dcp_data_length
, &data_length
);
1626 switch (service_id
) {
1627 case PNDCP_SERVICE_ID_GET
:
1628 pn_append_info(pinfo
, dcp_item
, "Get");
1630 case PNDCP_SERVICE_ID_SET
:
1631 pn_append_info(pinfo
, dcp_item
, "Set");
1633 case PNDCP_SERVICE_ID_IDENTIFY
:
1634 pn_append_info(pinfo
, dcp_item
, "Ident");
1636 case PNDCP_SERVICE_ID_HELLO
:
1637 pn_append_info(pinfo
, dcp_item
, "Hello");
1640 dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, tvb_captured_length_remaining(tvb
, offset
));
1644 switch (service_type
) {
1645 case PNDCP_SERVICE_TYPE_REQUEST
:
1646 pn_append_info(pinfo
, dcp_item
, " Req");
1648 case PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS
:
1649 pn_append_info(pinfo
, dcp_item
, " Ok ");
1652 case PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED
:
1653 pn_append_info(pinfo
, dcp_item
, " unsupported");
1657 dissect_pn_undecoded(tvb
, offset
, pinfo
, tree
, tvb_captured_length_remaining(tvb
, offset
));
1661 xid_str
= wmem_strdup_printf(pinfo
->pool
, ", Xid:0x%x", xid
);
1662 pn_append_info(pinfo
, dcp_item
, xid_str
);
1664 /* dissect a number of blocks (depending on the remaining length) */
1665 while(data_length
) {
1666 int ori_offset
= offset
;
1668 if (service_id
== PNDCP_SERVICE_ID_GET
&& service_type
== PNDCP_SERVICE_TYPE_REQUEST
) {
1670 offset
= dissect_PNDCP_Option(tvb
, offset
, pinfo
,
1671 tree
, dcp_item
, hf_pn_dcp_option
, true /* append_col */);
1673 offset
= dissect_PNDCP_Block(tvb
, offset
, pinfo
, tree
, dcp_item
, service_id
, is_response
);
1675 /* prevent an infinite loop */
1676 if (offset
<= ori_offset
|| data_length
< (offset
- ori_offset
)) {
1677 proto_tree_add_expert(tree
, pinfo
, &ei_pn_dcp_block_parse_error
,
1678 tvb
, ori_offset
, tvb_captured_length_remaining(tvb
, ori_offset
));
1681 data_length
-= (offset
- ori_offset
);
1686 /* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */
1688 dissect_PNDCP_Data_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1691 /* the tvb will NOT contain the frame_id here, so get it from dissection data! */
1692 uint16_t u16FrameID
= GPOINTER_TO_UINT(data
);
1694 proto_tree
*dcp_tree
;
1697 /* frame id must be in valid range (acyclic Real-Time, DCP) */
1698 if (u16FrameID
< FRAME_ID_DCP_HELLO
|| u16FrameID
> FRAME_ID_DCP_IDENT_RES
) {
1699 /* we are not interested in this packet */
1703 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PN-DCP");
1704 col_clear(pinfo
->cinfo
, COL_INFO
);
1706 /* subtree for DCP */
1707 item
= proto_tree_add_protocol_format(tree
, proto_pn_dcp
, tvb
, 0, tvb_get_ntohs(tvb
, 8) + 10,
1709 dcp_tree
= proto_item_add_subtree(item
, ett_pn_dcp
);
1711 /* dissect this PDU */
1712 dissect_PNDCP_PDU(tvb
, pinfo
, dcp_tree
, item
);
1719 proto_register_pn_dcp (void)
1721 static hf_register_info hf
[] = {
1722 { &hf_pn_dcp_service_id
,
1723 { "ServiceID", "pn_dcp.service_id",
1724 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_service_id
), 0x0,
1727 { &hf_pn_dcp_service_type
,
1728 { "ServiceType", "pn_dcp.service_type",
1729 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_service_type
), 0x0,
1733 { "Xid", "pn_dcp.xid",
1734 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1737 { &hf_pn_dcp_reserved8
,
1738 { "Reserved", "pn_dcp.reserved8",
1739 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1742 { &hf_pn_dcp_reserved16
,
1743 { "Reserved", "pn_dcp.reserved16",
1744 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1747 { &hf_pn_dcp_response_delay
,
1748 { "ResponseDelay", "pn_dcp.response_delay",
1749 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1752 { &hf_pn_dcp_data_length
,
1753 { "DCPDataLength", "pn_dcp.data_length",
1754 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1757 { &hf_pn_dcp_block_length
,
1758 { "DCPBlockLength", "pn_dcp.block_length",
1759 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1762 { &hf_pn_dcp_option
,
1763 { "Option", "pn_dcp.option",
1764 FT_UINT8
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(pn_dcp_option
), 0x0,
1768 { &hf_pn_dcp_suboption
,
1769 { "Suboption", "pn_dcp.suboption",
1770 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1774 { &hf_pn_dcp_block_error
,
1775 { "BlockError", "pn_dcp.block_error",
1776 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_block_error
), 0x0,
1780 { "Block", "pn_dcp.block",
1781 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1784 { &hf_pn_dcp_block_info
,
1785 { "BlockInfo", "pn_dcp.block_info",
1786 FT_UINT16
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(pn_dcp_block_info
), 0x0,
1789 { &hf_pn_dcp_block_qualifier
,
1790 { "BlockQualifier", "pn_dcp.block_qualifier",
1791 FT_UINT16
, BASE_DEC
, VALS(pn_dcp_block_qualifier
), 0x0,
1794 { &hf_pn_dcp_blockqualifier_r2f
,
1795 { "BlockQualifier: ResettoFactory", "pn_dcp.block_qualifier_reset",
1796 FT_UINT16
, BASE_DEC
, VALS(pn_dcp_BlockQualifier
), 0x0,
1799 { &hf_pn_dcp_blockqualifier
,
1800 { "BlockQualifier: ResetFactorySettings", "pn_dcp.block_qualifier_reset",
1801 FT_UINT16
, BASE_DEC
, VALS(pn_dcp_suboption_other
), 0x0,
1804 { &hf_pn_dcp_suboption_ip
,
1805 { "Suboption", "pn_dcp.suboption_ip",
1806 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_ip
), 0x0,
1809 { &hf_pn_dcp_suboption_ip_block_info
,
1810 { "BlockInfo", "pn_dcp.suboption_ip_block_info",
1811 FT_UINT16
, BASE_DEC
, VALS(pn_dcp_suboption_ip_block_info
), 0x0,
1814 { &hf_pn_dcp_suboption_ip_mac_address
,
1815 { "MAC Address", "pn_dcp.suboption_ip_mac_address",
1816 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1819 { &hf_pn_dcp_suboption_ip_ip
,
1820 { "IPaddress", "pn_dcp.suboption_ip_ip",
1821 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1824 { &hf_pn_dcp_suboption_ip_subnetmask
,
1825 { "Subnetmask", "pn_dcp.suboption_ip_subnetmask",
1826 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1829 { &hf_pn_dcp_suboption_ip_standard_gateway
,
1830 { "StandardGateway", "pn_dcp.suboption_ip_standard_gateway",
1831 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1834 { &hf_pn_dcp_suboption_device
,
1835 { "Suboption", "pn_dcp.suboption_device",
1836 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_device
), 0x0,
1839 { &hf_pn_dcp_suboption_device_typeofstation
,
1840 { "DeviceVendorValue", "pn_dcp.suboption_device_devicevendorvalue",
1841 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1844 { &hf_pn_dcp_suboption_device_nameofstation
,
1845 { "NameOfStation", "pn_dcp.suboption_device_nameofstation",
1846 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1849 { &hf_pn_dcp_suboption_vendor_id
,
1850 { "VendorID", "pn_dcp.suboption_vendor_id",
1851 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1854 { &hf_pn_dcp_suboption_device_id
,
1855 { "DeviceID", "pn_dcp.suboption_device_id",
1856 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1859 { &hf_pn_dcp_suboption_device_role
,
1860 { "DeviceRoleDetails", "pn_dcp.suboption_device_role",
1861 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1864 { &hf_pn_dcp_suboption_device_aliasname
,
1865 { "AliasName", "pn_dcp.suboption_device_aliasname",
1866 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1869 { &hf_pn_dcp_suboption_device_instance_high
,
1870 { "DeviceInstanceHigh", "pn_dcp.suboption_device_instance",
1871 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1874 { &hf_pn_dcp_suboption_device_instance_low
,
1875 { "DeviceInstanceLow", "pn_dcp.suboption_device_instance",
1876 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1879 { &hf_pn_dcp_suboption_device_oem_ven_id
,
1880 { "OEMVendorID", "pn_dcp.suboption_device_oem_ven_id",
1881 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1884 { &hf_pn_dcp_suboption_device_oem_dev_id
,
1885 { "OEMDeviceID", "pn_dcp.suboption_device_oem_dev_id",
1886 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1889 { &hf_pn_dcp_rsi_properties_value
,
1890 { "RsiPropertiesValue", "pn_dcp.suboption_device_rsi_properties_value",
1891 FT_UINT16
, BASE_HEX
, 0, 0x0,
1894 { &hf_pn_dcp_rsi_properties_value_bit0
,
1895 { "IP Stack", "pn_dcp.suboption_device_rsi_properties_value.bit0",
1896 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0001,
1899 { &hf_pn_dcp_rsi_properties_value_bit1
,
1900 { "CLRPC Interface", "pn_dcp.suboption_device_rsi_properties_value.bit1",
1901 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0002,
1904 { &hf_pn_dcp_rsi_properties_value_bit2
,
1905 { "RSI AR Interface", "pn_dcp.suboption_device_rsi_properties_value.bit2",
1906 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0004,
1909 { &hf_pn_dcp_rsi_properties_value_bit3
,
1910 { "RSI AR Read Implicit Interface", "pn_dcp.suboption_device_rsi_properties_value.bit3",
1911 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0008,
1914 { &hf_pn_dcp_rsi_properties_value_bit4
,
1915 { "RSI CIM Interface", "pn_dcp.suboption_device_rsi_properties_value.bit4",
1916 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0010,
1919 { &hf_pn_dcp_rsi_properties_value_bit5
,
1920 { "RSI CIM Read Implicit Interface", "pn_dcp.suboption_device_rsi_properties_value.bit5",
1921 FT_BOOLEAN
, 16, TFS(&pn_dcp_rsi_properties_value_bit
), 0x0020,
1924 { &hf_pn_dcp_rsi_properties_value_otherbits
,
1925 { "RsiPropertiesValue.Bit6-15", "pn_dcp.suboption_device_rsi_properties_value.otherbits",
1926 FT_UINT16
, BASE_HEX
, NULL
, 0xFFC0,
1929 { &hf_pn_dcp_vendor_id_high
,
1930 { "VendorIDHigh", "pn_dcp.vendor_id_high",
1931 FT_UINT16
, BASE_HEX
, NULL
, 0xFF00,
1934 { &hf_pn_dcp_vendor_id_low
,
1935 { "VendorIDLow", "pn_dcp.vendor_id_low",
1936 FT_UINT16
, BASE_HEX
, NULL
, 0x00FF,
1939 { &hf_pn_dcp_device_id_high
,
1940 { "DeviceIDHigh", "pn_dcp.device_id_high",
1941 FT_UINT16
, BASE_HEX
, NULL
, 0xFF00,
1944 { &hf_pn_dcp_device_id_low
,
1945 { "DeviceIDLow", "pn_dcp.device_id_low",
1946 FT_UINT16
, BASE_HEX
, NULL
, 0x00FF,
1949 { &hf_pn_dcp_instance_id_high
,
1950 { "InstanceHigh", "pn_dcp.instance_id_high",
1951 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1954 { &hf_pn_dcp_instance_id_low
,
1955 { "InstanceLow", "pn_dcp.instance_id_low",
1956 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1959 { &hf_pn_dcp_suboption_dhcp
,
1960 { "Suboption", "pn_dcp.suboption_dhcp",
1961 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_dhcp
), 0x0,
1964 { &hf_pn_dcp_suboption_dhcp_option_code
,
1965 { "Option-Code", "pn_dcp.suboption_dhcp_option_code",
1966 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_dhcp
), 0x0,
1969 { &hf_pn_dcp_suboption_dhcp_arbitrary_client_id
,
1970 { "Client ID", "pn_dcp.suboption_dhcp_client_id",
1971 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1974 { &hf_pn_dcp_suboption_dhcp_parameter_length
,
1975 { "DHCP Parameter Length", "pn_dcp.suboption_dhcp_parameter_length",
1976 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1979 { &hf_pn_dcp_suboption_dhcp_parameter_data
,
1980 { "DHCP Parameter Data", "pn_dcp.suboption_dhcp_parameter_data",
1981 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1984 { &hf_pn_dcp_suboption_dhcp_control_parameter_data
,
1985 { "DHCP Parameter Data", "pn_dcp.suboption_dhcp_parameter_data",
1986 FT_UINT8
, BASE_HEX
, VALS(pn_dcp_suboption_dhcp_control_parameter_data
), 0x0,
1989 { &hf_pn_dcp_suboption_control
,
1990 { "Suboption", "pn_dcp.suboption_control",
1991 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_control
), 0x0,
1994 { &hf_pn_dcp_suboption_control_option
,
1995 { "Option", "pn_dcp.suboption_control_option",
1996 FT_UINT8
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(pn_dcp_option
), 0x0,
1999 { &hf_pn_dcp_suboption_control_signal_value
,
2000 { "SignalValue", "pn_dcp.suboption_control_signal_value",
2001 FT_UINT16
, BASE_HEX
, VALS(pn_dcp_suboption_control_signal_value
), 0x0,
2004 { &hf_pn_dcp_suboption_deviceinitiative
,
2005 { "Suboption", "pn_dcp.suboption_deviceinitiative",
2006 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_deviceinitiative
), 0x0,
2009 { &hf_pn_dcp_deviceinitiative_value
,
2010 { "DeviceInitiativeValue", "pn_dcp.deviceinitiative_value",
2011 FT_UINT16
, BASE_DEC
, VALS(pn_dcp_deviceinitiative_value
), 0x0,
2014 { &hf_pn_dcp_suboption_tsn
,
2015 { "Suboption", "pn_dcp.suboption_tsn",
2016 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_tsn
), 0x0,
2019 { &hf_pn_dcp_suboption_tsn_domain_name
,
2020 { "TSNDomainName", "pn_dcp.suboption_tsn_domain_name",
2021 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2024 { &hf_pn_dcp_suboption_tsn_domain_uuid
,
2025 { "TSNDomainUUID", "pn_dcp.tsn_domain_uuid",
2026 FT_GUID
, BASE_NONE
, NULL
, 0x0,
2029 { &hf_pn_dcp_suboption_tsn_nme_prio
,
2030 { "NMEPrio", "pn_dcp.suboption_tsn_nme_prio",
2031 FT_UINT16
, BASE_DEC
| BASE_RANGE_STRING
, RVALS(pn_dcp_suboption_tsn_nme_prio
), 0x0,
2034 { &hf_pn_dcp_suboption_tsn_nme_parameter_uuid
,
2035 { "NMEParameterUUID", "pn_dcp.suboption_tsn_nme_parameter_uuid",
2036 FT_GUID
, BASE_NONE
, NULL
, 0x0,
2039 { &hf_pn_dcp_suboption_tsn_nme_agent
,
2040 { "NMEAgent", "pn_dcp.suboption_tsn_nme_agent",
2041 FT_GUID
, BASE_NONE
, NULL
, 0x0,
2044 { &hf_pn_dcp_suboption_all
,
2045 { "Suboption", "pn_dcp.suboption_all",
2046 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_all
), 0x0,
2049 { &hf_pn_dcp_suboption_manuf
,
2050 { "Suboption", "pn_dcp.suboption_manuf",
2051 FT_UINT8
, BASE_DEC
, VALS(pn_dcp_suboption_manuf
), 0x0,
2056 static int *ett
[] = {
2059 &ett_pn_dcp_rsi_properties_value
2062 static ei_register_info ei
[] = {
2063 { &ei_pn_dcp_block_parse_error
, { "pn_dcp.block_error.parse", PI_PROTOCOL
, PI_ERROR
, "parse error", EXPFILL
}},
2064 { &ei_pn_dcp_block_error_unknown
, { "pn_dcp.block_error.unknown", PI_RESPONSE_CODE
, PI_CHAT
, "Unknown", EXPFILL
}},
2065 { &ei_pn_dcp_ip_conflict
, { "pn_dcp.ip_conflict", PI_RESPONSE_CODE
, PI_NOTE
, "IP address conflict detected!", EXPFILL
}},
2068 expert_module_t
* expert_pn_dcp
;
2070 proto_pn_dcp
= proto_register_protocol ("PROFINET DCP", "PN-DCP", "pn_dcp");
2071 proto_register_field_array (proto_pn_dcp
, hf
, array_length (hf
));
2072 proto_register_subtree_array (ett
, array_length (ett
));
2073 expert_pn_dcp
= expert_register_protocol(proto_pn_dcp
);
2074 expert_register_field_array(expert_pn_dcp
, ei
, array_length(ei
));
2078 proto_reg_handoff_pn_dcp (void)
2080 /* register ourself as an heuristic pn-rt payload dissector */
2081 heur_dissector_add("pn_rt", dissect_PNDCP_Data_heur
, "PROFINET DCP IO", "pn_dcp_pn_rt", proto_pn_dcp
, HEURISTIC_ENABLE
);
2085 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2090 * indent-tabs-mode: nil
2093 * vi: set shiftwidth=4 tabstop=8 expandtab:
2094 * :indentSize=4:tabSize=8:noTabs=true: