1# coding: utf8 2% ProfinetIO DCP layer test campaign 3 4+ Syntax check 5= Import the ProfinetIO layer 6from scapy.contrib.pnio import * 7from scapy.contrib.pnio_dcp import * 8from scapy.config import conf 9import re 10old_conf_dissector = conf.debug_dissector 11conf.debug_dissector=True 12 13+ PNIO DCP PDU tests 14 15 16= DCP Identify All Request parsing 17 18p = Ether(b'\x01\x0e\xcf\x00\x00\x00\x01\x23\x45\x67\x89\xab\x88\x92\xfe\xfe' \ 19 b'\x05\x00\x01\x00\x00\x01\x00\x01\x00\x04\xff\xff\x00\x00\x00\x00' \ 20 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ 21 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 22 23assert p[Ether].dst == '01:0e:cf:00:00:00' 24assert p[Ether].src == '01:23:45:67:89:ab' 25assert p[Ether].type == 0x8892 26assert p[ProfinetIO].frameID == 0xfefe 27assert p[ProfinetDCP].service_id == 0x05 28assert p[ProfinetDCP].service_type == 0x00 29assert p[ProfinetDCP].xid == 0x1000001 30assert p[ProfinetDCP].reserved == 0x01 31assert p[ProfinetDCP].dcp_data_length == 0x04 32assert p[ProfinetDCP].option == 0xff 33assert p[ProfinetDCP].sub_option == 0xff 34assert p[ProfinetDCP].dcp_block_length == 0x00 35 36 37= DCP Set Request parsing 38 39p = Ether(b'\x01\x23\x45\x67\x89\xac\x01\x23\x45\x67\x89\xab\x88\x92\xfe\xfd' \ 40 b'\x04\x00\x00\x00\x00\x01\x00\x00\x00\x0c\x02\x02\x00\x08\x00\x01' \ 41 b'\x64\x65\x76\x69\x63\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ 42 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 43 44assert p[Ether].dst == '01:23:45:67:89:ac' 45assert p[Ether].src == '01:23:45:67:89:ab' 46assert p[Ether].type == 0x8892 47assert p[ProfinetIO].frameID == 0xfefd 48assert p[ProfinetDCP].service_id == 0x04 49assert p[ProfinetDCP].service_type == 0x00 50assert p[ProfinetDCP].xid == 0x0000001 51assert p[ProfinetDCP].reserved == 0x00 52assert p[ProfinetDCP].dcp_data_length == 0x0c 53assert p[ProfinetDCP].option == 0x02 54assert p[ProfinetDCP].sub_option == 0x02 55assert p[ProfinetDCP].dcp_block_length == 0x08 56assert p[ProfinetDCP].block_qualifier == 0x01 57 58 59= DCP Identify Response parsing 60 61p = Ether(b'\x94\x65\x9c\x51\x90\x7d\xac\x64\x17\x21\x35\xcf\x81\x00\x00\x00' \ 62 b'\x88\x92\xfe\xff\x05\x01\x01\x00\x00\x01\x00\x00\x00\x4e\x02\x05' \ 63 b'\x00\x04\x00\x00\x02\x07\x02\x01\x00\x09\x00\x00\x45\x54\x32\x30' \ 64 b'\x30\x53\x50\x00\x02\x02\x00\x08\x00\x00\x64\x65\x76\x69\x63\x65' \ 65 b'\x02\x03\x00\x06\x00\x00\x00\x2a\x03\x13\x02\x04\x00\x04\x00\x00' \ 66 b'\x01\x00\x02\x07\x00\x04\x00\x00\x00\x01\x01\x02\x00\x0e\x00\x01' \ 67 b'\xc0\xa8\x01\x0e\xff\xff\xff\x00\xc0\xa8\x01\x0e') 68 69# General 70assert p[ProfinetIO].frameID == 0xfeff 71assert p[ProfinetDCP].service_id == 0x05 72assert p[ProfinetDCP].service_type == 0x01 73assert p[ProfinetDCP].xid == 0x1000001 74assert p[ProfinetDCP].reserved == 0x00 75assert p[ProfinetDCP].dcp_data_length == 0x4e 76 77# - DCPDeviceOptionsBlock 78assert p[DCPDeviceOptionsBlock].option == 0x02 79assert p[DCPDeviceOptionsBlock].sub_option == 0x05 80assert p[DCPDeviceOptionsBlock].dcp_block_length == 0x04 81assert p[DCPDeviceOptionsBlock].block_info == 0x00 82 83# -- DeviceOption 84assert p[DeviceOption].option == 0x02 85assert p[DeviceOption].sub_option == 0x07 86 87# - DCPManufacturerSpecificBlock 88assert p[DCPManufacturerSpecificBlock].option == 0x02 89assert p[DCPManufacturerSpecificBlock].sub_option == 0x01 90assert p[DCPManufacturerSpecificBlock].dcp_block_length == 0x09 91assert p[DCPManufacturerSpecificBlock].block_info == 0x00 92assert p[DCPManufacturerSpecificBlock].device_vendor_value == b'ET200SP' 93 94# - DCPNameOfStationBlock 95assert p[DCPNameOfStationBlock].option == 0x02 96assert p[DCPNameOfStationBlock].sub_option == 0x02 97assert p[DCPNameOfStationBlock].dcp_block_length == 0x08 98assert p[DCPNameOfStationBlock].block_info == 0x00 99assert p[DCPNameOfStationBlock].name_of_station == b'device' 100 101# - DCPDeviceIDBlock 102assert p[DCPDeviceIDBlock].option == 0x02 103assert p[DCPDeviceIDBlock].sub_option == 0x03 104assert p[DCPDeviceIDBlock].dcp_block_length == 0x06 105assert p[DCPDeviceIDBlock].block_info == 0x00 106assert p[DCPDeviceIDBlock].vendor_id == 0x002a 107assert p[DCPDeviceIDBlock].device_id == 0x0313 108 109# - DCPDeviceRoleBlock 110assert p[DCPDeviceRoleBlock].option == 0x02 111assert p[DCPDeviceRoleBlock].sub_option == 0x04 112assert p[DCPDeviceRoleBlock].dcp_block_length == 0x04 113assert p[DCPDeviceRoleBlock].block_info == 0x00 114assert p[DCPDeviceRoleBlock].device_role_details == 0x01 115 116# - DCPDeviceInstanceBlock 117assert p[DCPDeviceInstanceBlock].option == 0x02 118assert p[DCPDeviceInstanceBlock].sub_option == 0x07 119assert p[DCPDeviceInstanceBlock].dcp_block_length == 0x04 120assert p[DCPDeviceInstanceBlock].block_info == 0x00 121assert p[DCPDeviceInstanceBlock].device_instance_high == 0x00 122assert p[DCPDeviceInstanceBlock].device_instance_low == 0x01 123 124# - DCPIPBlock 125assert p[DCPIPBlock].option == 0x01 126assert p[DCPIPBlock].sub_option == 0x02 127assert p[DCPIPBlock].dcp_block_length == 0x0e 128assert p[DCPIPBlock].block_info == 0x01 129assert p[DCPIPBlock].ip == "192.168.1.14" 130assert p[DCPIPBlock].netmask == "255.255.255.0" 131assert p[DCPIPBlock].gateway == "192.168.1.14" 132 133= DCP Identify Response parsing with new DCP packages (DCPOEMIDBlock, DCPDeviceInitiativeBlock) 134 135p = Ether(b'\x01\x0e\xcf\x00\x00\x00\x01\x23\x45\x67\x89\xab\x88\x92' \ 136 b'\xfe\xff\x05\x01\x01\x00\x00\x01\x00\x00\x00\x7a\x02\x02\x00\x02\x00' \ 137 b'\x00\x01\x02\x00\x0e\x00\x01\xc0\xa8\x01\x0b\xff\xff\xff\x00\x00\x00' \ 138 b'\x00\x00\x02\x03\x00\x06\x00\x00\x01\x6a\x04\x00\x02\x05\x00\x16\x00' \ 139 b'\x00\x01\x01\x01\x02\x02\x01\x02\x02\x02\x03\x02\x04\x02\x05\x02\x07' \ 140 b'\x02\x08\x06\x01\x02\x04\x00\x04\x00\x00\x01\x00\x06\x01\x00\x04\x00' \ 141 b'\x00\x00\x00\x02\x01\x00\x18\x00\x00\x31\x32\x33\x34\x20\x44\x44\x44' 142 b'\x20\x33\x58\x58\x32\x2d\x31\x32\x31\x2d\x30\x46\x44\x44\x02\x07\x00' \ 143 b'\x04\x00\x00\x00\x01\x02\x08\x00\x06\x00\x00\x01\x1e\xff\xff') 144 145# - General 146assert p[Ether].dst == '01:0e:cf:00:00:00' 147assert p[Ether].src == '01:23:45:67:89:ab' 148assert p[Ether].type == 0x8892 149assert p[ProfinetIO].frameID == 0xFEFF 150assert p[ProfinetDCP].service_id == 0x05 151assert p[ProfinetDCP].service_type == 0x01 152assert p[ProfinetDCP].xid == 0x1000001 153assert p[ProfinetDCP].reserved == 0x00 154assert p[ProfinetDCP].dcp_data_length == 122 155assert list(map(lambda x: type(x), p[ProfinetDCP].dcp_blocks)) == [DCPNameOfStationBlock, DCPIPBlock, DCPDeviceIDBlock, DCPDeviceOptionsBlock, DCPDeviceRoleBlock, DCPDeviceInitiativeBlock, DCPManufacturerSpecificBlock, DCPDeviceInstanceBlock, DCPOEMIDBlock] 156 157# - DCPNameOfStationBlock 158assert p[DCPNameOfStationBlock].option == 0x02 159assert p[DCPNameOfStationBlock].sub_option == 0x02 160 161# - DCPIPBlock 162assert p[DCPIPBlock].option == 0x01 163assert p[DCPIPBlock].sub_option == 0x02 164assert p[DCPIPBlock].dcp_block_length == 0x0E 165assert p[DCPIPBlock].ip == '192.168.1.11' 166assert p[DCPIPBlock].netmask == '255.255.255.0' 167assert p[DCPIPBlock].gateway == '0.0.0.0' 168 169# - DCPDeviceInitiativeBlock 170assert p[DCPDeviceInitiativeBlock].option == 0x06 171assert p[DCPDeviceInitiativeBlock].sub_option == 0x01 172assert p[DCPDeviceInitiativeBlock].dcp_block_length == 0x04 173assert p[DCPDeviceInitiativeBlock].device_initiative == 0x0000 174 175# - DCPManufacturerSpecificBlock 176assert p[DCPManufacturerSpecificBlock].option == 0x02 177assert p[DCPManufacturerSpecificBlock].sub_option == 0x01 178assert p[DCPManufacturerSpecificBlock].device_vendor_value == b'1234 DDD 3XX2-121-0FDD' 179 180# - DCPOEMIDBlock 181assert p[DCPOEMIDBlock].option == 0x02 182assert p[DCPOEMIDBlock].sub_option == 0x08 183assert p[DCPOEMIDBlock].dcp_block_length == 0x06 184assert p[DCPOEMIDBlock].vendor_id == 0x011e 185assert p[DCPOEMIDBlock].device_id == 0xffff 186 187= DCP Set Request parsing 188 189p = Ether(b'\x94\x65\x9c\x51\x90\x7d\xac\x64\x17\x21\x35\xcf\x81\x00\x00\x00' \ 190 b'\x88\x92\xfe\xfd\x04\x01\x00\x00\x00\x01\x00\x00\x00\x08\x05\x04' \ 191 b'\x00\x03\x02\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ 192 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 193 194assert p[ProfinetIO].frameID == 0xfefd 195assert p[ProfinetDCP].service_id == 0x04 196assert p[ProfinetDCP].service_type == 0x01 197assert p[ProfinetDCP].xid == 0x0000001 198assert p[ProfinetDCP].reserved == 0x00 199assert p[ProfinetDCP].dcp_data_length == 0x08 200 201assert p[DCPControlBlock].option == 0x05 202assert p[DCPControlBlock].sub_option == 0x04 203assert p[DCPControlBlock].dcp_block_length == 0x03 204assert p[DCPControlBlock].response == 0x02 205assert p[DCPControlBlock].response_sub_option == 0x02 206assert p[DCPControlBlock].block_error == 0x00 207 208 209= DCP Set Full IP Suite Request parsing 210 211p = Ether(b'\x12\x34\x00\x78\x90\xab\xc8\x5b\x76\xe6\x89\xdf' \ 212 b'\x88\x92\xfe\xfd\x04\x00\x00\x00\x00\x04\x00\x00' \ 213 b'\x00\x28\x01\x03\x00\x1e\x00\x00\xc0\xa8\x01\xab' \ 214 b'\xff\xff\xff\x00\xc0\xa8\x01\x01\x01\x02\x03\x04' \ 215 b'\x05\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00') 216 217assert p[ProfinetIO].frameID == 0xfefd 218assert p[ProfinetDCP].service_id == 0x04 219assert p[ProfinetDCP].service_type == 0x00 220assert p[ProfinetDCP].xid == 0x0000004 221assert p[ProfinetDCP].reserved == 0x00 222assert p[ProfinetDCP].dcp_data_length == 40 223assert p[ProfinetDCP].option == 0x01 224assert p[ProfinetDCP].sub_option == 0x03 225assert p[ProfinetDCP].ip == "192.168.1.171" 226assert p[ProfinetDCP].netmask == "255.255.255.0" 227assert p[ProfinetDCP].gateway == "192.168.1.1" 228assert p[ProfinetDCP].dnsaddr[0] == "1.2.3.4" 229assert p[ProfinetDCP].dnsaddr[1] == "5.6.7.8" 230assert p[ProfinetDCP].dnsaddr[2] == "0.0.0.0" 231assert p[ProfinetDCP].dnsaddr[3] == "0.0.0.0" 232 233 234= DCP Identify All Request crafting 235 236# dcp_data_length cannot be calculated automatically at this time 237p = ProfinetIO(frameID=DCP_IDENTIFY_REQUEST_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_IDENTIFY, service_type=DCP_REQUEST, option=255, sub_option=255, dcp_data_length=4) 238 239assert p[ProfinetIO].frameID == 0xfefe 240assert p[ProfinetDCP].service_id == 0x05 241assert p[ProfinetDCP].service_type == 0x00 242assert p[ProfinetDCP].xid == 0x1000001 243assert p[ProfinetDCP].reserved == 0x00 244assert p[ProfinetDCP].dcp_data_length == 0x04 245assert p[ProfinetDCP].option == 0xff 246assert p[ProfinetDCP].sub_option == 0xff 247assert p[ProfinetDCP].dcp_block_length == 0x00 248 249 250= DCP Set Name Request with specified name crafting 251 252p = ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) / ProfinetDCP ( service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST, option=2, sub_option=2, name_of_station="device", dcp_block_length=8, dcp_data_length=12) 253 254assert p[ProfinetIO].frameID == 0xfefd 255assert p[ProfinetDCP].service_id == 0x04 256assert p[ProfinetDCP].service_type == 0x00 257assert p[ProfinetDCP].xid == 0x1000001 258assert p[ProfinetDCP].reserved == 0x00 259assert p[ProfinetDCP].dcp_data_length == 0x0c 260assert p[ProfinetDCP].option == 0x02 261assert p[ProfinetDCP].sub_option == 0x02 262assert p[ProfinetDCP].dcp_block_length == 0x08 263assert p[ProfinetDCP].block_qualifier == 0x0001 264 265 266= DCP Identify Response crafting 267 268p = ProfinetIO(frameID=DCP_IDENTIFY_RESPONSE_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_IDENTIFY, service_type=DCP_RESPONSE, dcp_data_length=12) / DCPNameOfStationBlock(name_of_station="device", dcp_block_length=8) 269 270assert p[ProfinetIO].frameID == 0xfeff 271assert p[ProfinetDCP].service_id == 0x05 272assert p[ProfinetDCP].service_type == 0x01 273assert p[ProfinetDCP].xid == 0x1000001 274assert p[ProfinetDCP].reserved == 0x00 275assert p[ProfinetDCP].dcp_data_length == 0x0c 276assert p[DCPNameOfStationBlock].option == 0x02 277assert p[DCPNameOfStationBlock].sub_option == 0x02 278assert p[DCPNameOfStationBlock].dcp_block_length == 0x08 279assert p[DCPNameOfStationBlock].block_info == 0x00 280assert p[DCPNameOfStationBlock].name_of_station == b'device' 281 282 283= DCP Set Full IP Suite Request crafting 284 285p = ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST, option=1, sub_option=3, ip='192.168.1.171', netmask='255.255.255.0', gateway='192.168.1.1', dnsaddr=['1.2.3.4', '5.6.7.8'], dcp_data_length=40, dcp_block_length=30) 286 287assert p[ProfinetIO].frameID == 0xfefd 288assert p[ProfinetDCP].service_id == 0x04 289assert p[ProfinetDCP].service_type == 0x00 290assert p[ProfinetDCP].xid == 0x1000001 291assert p[ProfinetDCP].reserved == 0x00 292assert p[ProfinetDCP].dcp_data_length == 40 293assert p[ProfinetDCP].option == 0x01 294assert p[ProfinetDCP].sub_option == 0x03 295assert p[ProfinetDCP].ip == "192.168.1.171" 296assert p[ProfinetDCP].netmask == "255.255.255.0" 297assert p[ProfinetDCP].gateway == "192.168.1.1" 298assert p[ProfinetDCP].dnsaddr[0] == "1.2.3.4" 299assert p[ProfinetDCP].dnsaddr[1] == "5.6.7.8" 300 301 302conf.debug_dissector = old_conf_dissector 303