epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / plugins / epan / profinet / packet-pn-dcp.c
blob8f9972544ebfd7383a2660841674cac2e0897f1d
1 /* packet-pn-dcp.c
2 * Routines for PN-DCP (PROFINET Discovery and basic Configuration Protocol)
3 * packet dissection.
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
20 * dataframes.
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)
30 #include "config.h"
32 #include <glib.h>
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>
39 #include <epan/tfs.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);
48 int proto_pn_dcp;
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 */
151 { 0, NULL }
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 */
163 { 0, NULL }
166 static const value_string pn_dcp_block_error[] = {
167 { 0x00, "Ok" },
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 */
175 { 0, NULL }
178 static const range_string pn_dcp_block_info[] = {
179 { 0x0000, 0xFFFF, "Reserved" },
180 { 0, 0, NULL }
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 */
187 { 0, NULL }
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" },
211 { 0, NULL }
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" },
238 { 0, 0, NULL }
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 */
251 { 0, NULL }
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 */
262 { 0, NULL }
265 static const value_string pn_dcp_suboption_control_signal_value[] = {
266 {0x0100, "Flash Once"},
267 {0, NULL}
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 */
292 { 0, NULL }
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" },
311 { 0, NULL }
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" },
321 { 0, 0, NULL }
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[] = {
328 { 12, "Host name" },
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 */
338 { 0, NULL }
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" },
345 { 0, NULL }
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 */
364 { 0, NULL }
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 */
373 { 0, NULL }
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 */
380 { 0, NULL }
383 static const value_string pn_dcp_suboption_all[] = {
384 { 0xff, "ALL Selector" },
385 /* all other reserved */
386 { 0, NULL }
389 static const value_string pn_dcp_suboption_other[] = {
390 { 0x00, "Default" },
391 /* all other reserved */
392 { 0, NULL }
395 static const value_string pn_dcp_suboption_manuf[] = {
396 /* none known */
397 { 0, NULL }
404 /* dissect the option field */
405 static int
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)
409 uint8_t option;
410 uint8_t suboption;
411 const value_string *val_str;
413 offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hfindex, &option);
414 switch (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;
418 break;
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;
422 break;
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;
426 break;
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;
430 break;
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;
434 break;
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;
438 break;
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;
442 break;
443 default:
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"));
452 if (append_col) {
453 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(suboption, val_str, "Unknown"));
456 return offset;
460 /* dissect the "IP" suboption */
461 static int
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)
466 uint8_t suboption;
467 uint16_t block_length;
468 uint16_t block_info;
469 uint16_t block_qualifier;
470 bool have_block_info = false;
471 bool have_block_qualifier = false;
472 uint8_t mac[6];
473 uint32_t ip;
474 proto_item *item = NULL;
475 address addr;
478 /* SuboptionIPParameter */
479 offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip, &suboption);
480 /* DCPBlockLength */
481 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length);
483 switch (suboption) {
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");
489 /* BlockInfo? */
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;
495 block_length -= 2;
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;
502 block_length -= 2;
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));
517 break;
518 case PNDCP_SUBOPTION_IP_IP:
519 pn_append_info(pinfo, dcp_item, ", IP");
520 proto_item_append_text(block_item, "IP/IP");
522 /* BlockInfo? */
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);
527 if (tree) {
528 item = proto_tree_add_uint(tree, hf_pn_dcp_suboption_ip_block_info, tvb, offset, 2, block_info);
530 offset += 2;
531 proto_item_append_text(block_item, ", BlockInfo: %s",
532 val_to_str_const(block_info, pn_dcp_suboption_ip_block_info, "Undecoded"));
533 block_length -= 2;
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"));
544 block_length -= 2;
547 /* IPParameterValue ... */
549 /* IPAddress */
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));
554 /* Subnetmask */
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));
563 break;
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");
568 /* BlockInfo? */
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;
574 block_length -= 2;
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;
581 block_length -= 2;
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"));
593 /* IPAddress */
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));
598 /* Subnetmask */
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));
608 /* IPAddress_1 */
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));
613 /* IPAddress_2 */
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));
618 /* IPAddress_3 */
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));
623 /* IPAddress_4 */
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));
628 break;
629 default:
630 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length);
633 return offset;
637 /* dissect the "device" suboption */
638 static int
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)
643 uint8_t suboption;
644 uint16_t block_length;
645 char *info_str;
646 uint8_t device_role;
647 uint16_t vendor_id;
648 uint16_t device_id;
649 char *typeofstation;
650 char *nameofstation;
651 char *aliasname;
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);
667 /* DCPBlockLength */
668 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length);
670 /* BlockInfo? */
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;
676 block_length -= 2;
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;
683 block_length -= 2;
686 switch (suboption) {
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
699 * such as that.
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 */
721 if (is_response) {
722 conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0);
724 else {
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;
740 break;
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
756 * domain name?
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 */
778 if (is_response) {
779 conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0);
781 else {
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;
797 break;
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 */
809 if (is_response) {
810 conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0);
812 else {
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);
840 break;
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"));
850 if (have_block_info)
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");
860 break;
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 */);
878 break;
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
888 * " and:
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
904 * RFC 5890 Punycode.
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;
919 break;
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);
935 break;
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);
950 break;
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,
963 NULL
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);
968 offset = offset + 2;
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"));
995 break;
996 default:
997 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length);
1000 return offset;
1003 /* dissect the "tsn" suboption */
1004 static int
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)
1009 uint8_t suboption;
1010 uint16_t block_length;
1011 char *domain_name;
1012 uint16_t nme_prio;
1013 e_guid_t tsn_domain_uuid;
1014 e_guid_t nme_parameter_uuid;
1015 e_guid_t nme_name_uuid;
1016 uint16_t vendor_id;
1017 uint16_t device_id;
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);
1034 /* BlockInfo? */
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;
1040 block_length -= 2;
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;
1047 block_length -= 2;
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);
1068 is_zeros = true;
1070 for (int i = 0; i < 8; i++)
1072 if (tsn_domain_uuid.data4[i] != 0)
1074 is_zeros = false;
1075 break;
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");
1081 else
1082 proto_item_append_text(block_item, ", UUID identifying a TSN domain using SNMP/ LLDP/ DCP");
1084 break;
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");
1110 else
1111 proto_item_append_text(block_item, ", Reserved");
1114 break;
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"));
1133 is_zeros = true;
1135 for (int i = 0; i < 8; i++)
1137 if (nme_parameter_uuid.data4[i] != 0)
1139 is_zeros = false;
1140 break;
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");
1145 else
1146 proto_item_append_text(block_item, ", UUID identifying an NME parameter set within the TSN domain.");
1148 break;
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"));
1166 is_zeros = true;
1167 for (int i = 0; i < 8; i++)
1169 if (nme_name_uuid.data4[i] != 0)
1171 is_zeros = false;
1172 break;
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");
1178 else
1179 proto_item_append_text(block_item, ", UUID identifying an NME using SNMP / LLDP / DCP");
1181 break;
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)
1195 // CIMVDIValue
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);
1227 break;
1229 default:
1230 pn_append_info(pinfo, dcp_item, ", TSN/Reserved");
1231 proto_item_append_text(block_item, "TSN/Reserved");
1234 return offset;
1237 /* dissect the "DHCP" suboption */
1238 static int
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_)
1243 uint8_t suboption;
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;
1261 /* BlockInfo? */
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;
1267 block_length -= 2;
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;
1273 block_length -= 2;
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");
1296 else {
1297 proto_item_append_text(block_item, ", Client-ID: Name of Station");
1300 else {
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);
1317 break;
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);
1332 break;
1333 default:
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");
1341 return offset;
1345 /* dissect the "control" suboption */
1346 static int
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_)
1351 uint8_t suboption;
1352 uint16_t block_length;
1353 uint16_t block_qualifier;
1354 uint16_t BlockQualifier;
1355 uint16_t u16SignalValue;
1356 char *info_str;
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");
1368 else {
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);
1374 break;
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);
1379 break;
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);
1384 block_length -= 2;
1386 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control_signal_value, &u16SignalValue);
1387 break;
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);
1393 if (tree) {
1394 item = proto_tree_add_uint(tree, hf_pn_dcp_block_error, tvb, offset, 1, block_error);
1396 offset += 1;
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"));
1407 break;
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");
1411 block_length -= 2;
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"));
1415 block_length -= 2;
1416 break;
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"));
1425 block_length -= 2;
1427 break;
1428 default:
1429 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length);
1433 return offset;
1437 /* dissect the "deviceinitiative" suboption */
1438 static int
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)
1443 uint8_t suboption;
1444 uint16_t block_length;
1445 uint16_t block_info;
1446 uint16_t block_qualifier;
1447 uint16_t value;
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");
1456 /* BlockInfo? */
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"));
1463 block_length -= 2;
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"));
1471 block_length -= 2;
1474 /* DeviceInitiativeValue */
1475 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_deviceinitiative_value, &value);
1477 return offset;
1481 /* dissect the "all" suboption */
1482 static int
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_)
1487 uint8_t suboption;
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) {
1495 case 255: /* All */
1496 pn_append_info(pinfo, dcp_item, ", All");
1497 proto_item_append_text(block_item, "All/All");
1498 break;
1499 default:
1500 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length);
1503 return offset;
1507 /* dissect the "manufacturer" suboption */
1508 static int
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);
1525 return offset;
1529 /* dissect one DCP block */
1530 static int
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)
1535 uint8_t option;
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);
1580 else
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);
1594 return offset;
1598 /* dissect a whole DCP PDU */
1599 static void
1600 dissect_PNDCP_PDU(tvbuff_t *tvb,
1601 packet_info *pinfo, proto_tree *tree, proto_item *dcp_item)
1603 uint8_t service_id;
1604 uint8_t service_type;
1605 uint32_t xid;
1606 uint16_t response_delay;
1607 uint16_t data_length;
1608 int offset = 0;
1609 char *xid_str;
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);
1616 offset += 4;
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);
1620 } else {
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");
1629 break;
1630 case PNDCP_SERVICE_ID_SET:
1631 pn_append_info(pinfo, dcp_item, "Set");
1632 break;
1633 case PNDCP_SERVICE_ID_IDENTIFY:
1634 pn_append_info(pinfo, dcp_item, "Ident");
1635 break;
1636 case PNDCP_SERVICE_ID_HELLO:
1637 pn_append_info(pinfo, dcp_item, "Hello");
1638 break;
1639 default:
1640 dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset));
1641 return;
1644 switch (service_type) {
1645 case PNDCP_SERVICE_TYPE_REQUEST:
1646 pn_append_info(pinfo, dcp_item, " Req");
1647 break;
1648 case PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS:
1649 pn_append_info(pinfo, dcp_item, " Ok ");
1650 is_response = true;
1651 break;
1652 case PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED:
1653 pn_append_info(pinfo, dcp_item, " unsupported");
1654 is_response = true;
1655 break;
1656 default:
1657 dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset));
1658 return;
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) {
1669 /* Selectors */
1670 offset = dissect_PNDCP_Option(tvb, offset, pinfo,
1671 tree, dcp_item, hf_pn_dcp_option, true /* append_col */);
1672 } else {
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));
1679 break;
1681 data_length -= (offset - ori_offset);
1686 /* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */
1687 static bool
1688 dissect_PNDCP_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1689 void *data)
1691 /* the tvb will NOT contain the frame_id here, so get it from dissection data! */
1692 uint16_t u16FrameID = GPOINTER_TO_UINT(data);
1693 proto_item *item;
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 */
1700 return false;
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,
1708 "PROFINET DCP, ");
1709 dcp_tree = proto_item_add_subtree(item, ett_pn_dcp);
1711 /* dissect this PDU */
1712 dissect_PNDCP_PDU(tvb, pinfo, dcp_tree, item);
1714 return true;
1718 void
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,
1725 NULL, HFILL }},
1727 { &hf_pn_dcp_service_type,
1728 { "ServiceType", "pn_dcp.service_type",
1729 FT_UINT8, BASE_DEC, VALS(pn_dcp_service_type), 0x0,
1730 NULL, HFILL }},
1732 { &hf_pn_dcp_xid,
1733 { "Xid", "pn_dcp.xid",
1734 FT_UINT32, BASE_HEX, NULL, 0x0,
1735 NULL, HFILL }},
1737 { &hf_pn_dcp_reserved8,
1738 { "Reserved", "pn_dcp.reserved8",
1739 FT_UINT8, BASE_DEC, NULL, 0x0,
1740 NULL, HFILL }},
1742 { &hf_pn_dcp_reserved16,
1743 { "Reserved", "pn_dcp.reserved16",
1744 FT_UINT16, BASE_DEC, NULL, 0x0,
1745 NULL, HFILL }},
1747 { &hf_pn_dcp_response_delay,
1748 { "ResponseDelay", "pn_dcp.response_delay",
1749 FT_UINT16, BASE_DEC, NULL, 0x0,
1750 NULL, HFILL }},
1752 { &hf_pn_dcp_data_length,
1753 { "DCPDataLength", "pn_dcp.data_length",
1754 FT_UINT16, BASE_DEC, NULL, 0x0,
1755 NULL, HFILL }},
1757 { &hf_pn_dcp_block_length,
1758 { "DCPBlockLength", "pn_dcp.block_length",
1759 FT_UINT16, BASE_DEC, NULL, 0x0,
1760 NULL, HFILL }},
1762 { &hf_pn_dcp_option,
1763 { "Option", "pn_dcp.option",
1764 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(pn_dcp_option), 0x0,
1765 NULL, HFILL }},
1767 #if 0
1768 { &hf_pn_dcp_suboption,
1769 { "Suboption", "pn_dcp.suboption",
1770 FT_UINT8, BASE_DEC, NULL, 0x0,
1771 NULL, HFILL }},
1772 #endif
1774 { &hf_pn_dcp_block_error,
1775 { "BlockError", "pn_dcp.block_error",
1776 FT_UINT8, BASE_DEC, VALS(pn_dcp_block_error), 0x0,
1777 NULL, HFILL }},
1779 { &hf_pn_dcp_block,
1780 { "Block", "pn_dcp.block",
1781 FT_NONE, BASE_NONE, NULL, 0x0,
1782 NULL, HFILL }},
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,
1787 NULL, HFILL }},
1789 { &hf_pn_dcp_block_qualifier,
1790 { "BlockQualifier", "pn_dcp.block_qualifier",
1791 FT_UINT16, BASE_DEC, VALS(pn_dcp_block_qualifier), 0x0,
1792 NULL, HFILL }},
1794 { &hf_pn_dcp_blockqualifier_r2f,
1795 { "BlockQualifier: ResettoFactory", "pn_dcp.block_qualifier_reset",
1796 FT_UINT16, BASE_DEC, VALS(pn_dcp_BlockQualifier), 0x0,
1797 NULL, HFILL }},
1799 { &hf_pn_dcp_blockqualifier,
1800 { "BlockQualifier: ResetFactorySettings", "pn_dcp.block_qualifier_reset",
1801 FT_UINT16, BASE_DEC, VALS(pn_dcp_suboption_other), 0x0,
1802 NULL, HFILL }},
1804 { &hf_pn_dcp_suboption_ip,
1805 { "Suboption", "pn_dcp.suboption_ip",
1806 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_ip), 0x0,
1807 NULL, HFILL }},
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,
1812 NULL, HFILL }},
1814 { &hf_pn_dcp_suboption_ip_mac_address,
1815 { "MAC Address", "pn_dcp.suboption_ip_mac_address",
1816 FT_ETHER, BASE_NONE, NULL, 0x0,
1817 NULL, HFILL }},
1819 { &hf_pn_dcp_suboption_ip_ip,
1820 { "IPaddress", "pn_dcp.suboption_ip_ip",
1821 FT_IPv4, BASE_NONE, NULL, 0x0,
1822 NULL, HFILL }},
1824 { &hf_pn_dcp_suboption_ip_subnetmask,
1825 { "Subnetmask", "pn_dcp.suboption_ip_subnetmask",
1826 FT_IPv4, BASE_NONE, NULL, 0x0,
1827 NULL, HFILL }},
1829 { &hf_pn_dcp_suboption_ip_standard_gateway,
1830 { "StandardGateway", "pn_dcp.suboption_ip_standard_gateway",
1831 FT_IPv4, BASE_NONE, NULL, 0x0,
1832 NULL, HFILL }},
1834 { &hf_pn_dcp_suboption_device,
1835 { "Suboption", "pn_dcp.suboption_device",
1836 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_device), 0x0,
1837 NULL, HFILL }},
1839 { &hf_pn_dcp_suboption_device_typeofstation,
1840 { "DeviceVendorValue", "pn_dcp.suboption_device_devicevendorvalue",
1841 FT_STRING, BASE_NONE, NULL, 0x0,
1842 NULL, HFILL }},
1844 { &hf_pn_dcp_suboption_device_nameofstation,
1845 { "NameOfStation", "pn_dcp.suboption_device_nameofstation",
1846 FT_STRING, BASE_NONE, NULL, 0x0,
1847 NULL, HFILL }},
1849 { &hf_pn_dcp_suboption_vendor_id,
1850 { "VendorID", "pn_dcp.suboption_vendor_id",
1851 FT_UINT16, BASE_HEX, NULL, 0x0,
1852 NULL, HFILL }},
1854 { &hf_pn_dcp_suboption_device_id,
1855 { "DeviceID", "pn_dcp.suboption_device_id",
1856 FT_UINT16, BASE_HEX, NULL, 0x0,
1857 NULL, HFILL }},
1859 { &hf_pn_dcp_suboption_device_role,
1860 { "DeviceRoleDetails", "pn_dcp.suboption_device_role",
1861 FT_UINT8, BASE_HEX, NULL, 0x0,
1862 NULL, HFILL }},
1864 { &hf_pn_dcp_suboption_device_aliasname,
1865 { "AliasName", "pn_dcp.suboption_device_aliasname",
1866 FT_STRING, BASE_NONE, NULL, 0x0,
1867 NULL, HFILL }},
1869 { &hf_pn_dcp_suboption_device_instance_high,
1870 { "DeviceInstanceHigh", "pn_dcp.suboption_device_instance",
1871 FT_UINT8, BASE_HEX, NULL, 0x0,
1872 NULL, HFILL }},
1874 { &hf_pn_dcp_suboption_device_instance_low,
1875 { "DeviceInstanceLow", "pn_dcp.suboption_device_instance",
1876 FT_UINT8, BASE_HEX, NULL, 0x0,
1877 NULL, HFILL }},
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,
1882 NULL, HFILL }},
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,
1887 NULL, HFILL }},
1889 { &hf_pn_dcp_rsi_properties_value,
1890 { "RsiPropertiesValue", "pn_dcp.suboption_device_rsi_properties_value",
1891 FT_UINT16, BASE_HEX, 0, 0x0,
1892 NULL, HFILL } },
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,
1897 NULL, HFILL } },
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,
1902 NULL, HFILL } },
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,
1907 NULL, HFILL } },
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,
1912 NULL, HFILL } },
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,
1917 NULL, HFILL } },
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,
1922 NULL, HFILL } },
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,
1927 NULL, HFILL } },
1929 { &hf_pn_dcp_vendor_id_high,
1930 { "VendorIDHigh", "pn_dcp.vendor_id_high",
1931 FT_UINT16, BASE_HEX, NULL, 0xFF00,
1932 NULL, HFILL } },
1934 { &hf_pn_dcp_vendor_id_low,
1935 { "VendorIDLow", "pn_dcp.vendor_id_low",
1936 FT_UINT16, BASE_HEX, NULL, 0x00FF,
1937 NULL, HFILL } },
1939 { &hf_pn_dcp_device_id_high,
1940 { "DeviceIDHigh", "pn_dcp.device_id_high",
1941 FT_UINT16, BASE_HEX, NULL, 0xFF00,
1942 NULL, HFILL } },
1944 { &hf_pn_dcp_device_id_low,
1945 { "DeviceIDLow", "pn_dcp.device_id_low",
1946 FT_UINT16, BASE_HEX, NULL, 0x00FF,
1947 NULL, HFILL } },
1949 { &hf_pn_dcp_instance_id_high,
1950 { "InstanceHigh", "pn_dcp.instance_id_high",
1951 FT_UINT8, BASE_HEX, NULL, 0x0,
1952 NULL, HFILL } },
1954 { &hf_pn_dcp_instance_id_low,
1955 { "InstanceLow", "pn_dcp.instance_id_low",
1956 FT_UINT8, BASE_HEX, NULL, 0x0,
1957 NULL, HFILL } },
1959 { &hf_pn_dcp_suboption_dhcp,
1960 { "Suboption", "pn_dcp.suboption_dhcp",
1961 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_dhcp), 0x0,
1962 NULL, HFILL }},
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,
1967 NULL, HFILL }},
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,
1972 NULL, HFILL }},
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,
1977 NULL, HFILL } },
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,
1982 NULL, HFILL } },
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,
1987 NULL, HFILL } },
1989 { &hf_pn_dcp_suboption_control,
1990 { "Suboption", "pn_dcp.suboption_control",
1991 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_control), 0x0,
1992 NULL, HFILL }},
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,
1997 NULL, HFILL }},
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,
2002 NULL, HFILL } },
2004 { &hf_pn_dcp_suboption_deviceinitiative,
2005 { "Suboption", "pn_dcp.suboption_deviceinitiative",
2006 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_deviceinitiative), 0x0,
2007 NULL, HFILL }},
2009 { &hf_pn_dcp_deviceinitiative_value,
2010 { "DeviceInitiativeValue", "pn_dcp.deviceinitiative_value",
2011 FT_UINT16, BASE_DEC, VALS(pn_dcp_deviceinitiative_value), 0x0,
2012 NULL, HFILL }},
2014 { &hf_pn_dcp_suboption_tsn,
2015 { "Suboption", "pn_dcp.suboption_tsn",
2016 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_tsn), 0x0,
2017 NULL, HFILL } },
2019 { &hf_pn_dcp_suboption_tsn_domain_name,
2020 { "TSNDomainName", "pn_dcp.suboption_tsn_domain_name",
2021 FT_STRING, BASE_NONE, NULL, 0x0,
2022 NULL, HFILL } },
2024 { &hf_pn_dcp_suboption_tsn_domain_uuid,
2025 { "TSNDomainUUID", "pn_dcp.tsn_domain_uuid",
2026 FT_GUID, BASE_NONE, NULL, 0x0,
2027 NULL, HFILL } },
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,
2032 NULL, HFILL } },
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,
2037 NULL, HFILL } },
2039 { &hf_pn_dcp_suboption_tsn_nme_agent,
2040 { "NMEAgent", "pn_dcp.suboption_tsn_nme_agent",
2041 FT_GUID, BASE_NONE, NULL, 0x0,
2042 NULL, HFILL } },
2044 { &hf_pn_dcp_suboption_all,
2045 { "Suboption", "pn_dcp.suboption_all",
2046 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_all), 0x0,
2047 NULL, HFILL }},
2049 { &hf_pn_dcp_suboption_manuf,
2050 { "Suboption", "pn_dcp.suboption_manuf",
2051 FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_manuf), 0x0,
2052 NULL, HFILL }},
2056 static int *ett[] = {
2057 &ett_pn_dcp,
2058 &ett_pn_dcp_block,
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));
2077 void
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
2087 * Local variables:
2088 * c-basic-offset: 4
2089 * tab-width: 8
2090 * indent-tabs-mode: nil
2091 * End:
2093 * vi: set shiftwidth=4 tabstop=8 expandtab:
2094 * :indentSize=4:tabSize=8:noTabs=true: