class ENIP_SendUnitData_Item(scapy_all.Packet): name = "ENIP_SendUnitData_Item" fields_desc = [ scapy_all.LEShortEnumField( "type_id", 0, { 0x0000: "null_address", # NULL Address 0x00a1: "conn_address", # Address for connection based requests 0x00b1: "conn_packet", # Connected Transport packet 0x00b2: "unconn_message", # Unconnected Messages (eg. used within CIP command SendRRData) 0x0100: "listservices_response", # ListServices response }), scapy_all.LEShortField("length", None), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay
class ENIP_TCP(scapy_all.Packet): """Ethernet/IP packet over TCP""" name = "ENIP_TCP" fields_desc = [ #add missing bits here scapy_all.LEShortEnumField( "command_id", None, { 0x0004: "ListServices", 0x0063: "ListIdentity", 0x0064: "ListInterfaces", 0x0065: "RegisterSession", 0x0066: "UnregisterSession", 0x006f: "SendRRData", # Send Request/Reply data 0x0070: "SendUnitData", }), scapy_all.LEShortField("length", None), scapy_all.LEIntField("session", 0), scapy_all.LEIntEnumField("status", 0, {0: "success"}), scapy_all.LELongField("sender_context", 0), scapy_all.LEIntField("options", 0), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay
class ENIP_ListIdentity_TargetItem(scapy_all.Packet): name = "ENIP_ListIdentity_TargetItem" fields_desc = [ scapy_all.LEShortField("item_type_code", 0), scapy_all.LEShortField("length", 0), scapy_all.LEShortField("encapsulation_version", 1), scapy_all.PacketField("ListIdentityItems", ENIP_ListIdentity_SocketItem(), ENIP_ListIdentity_SocketItem), #, count_from=1), scapy_all.LEShortField("vendor_ID", 0), scapy_all.LEShortEnumField("device_type", 0x21, DEVICE_PROFILES), scapy_all.LEShortField("product_code", 0), scapy_all.PacketField("ENIP_DeviceRevision", ENIP_DeviceRevision(), ENIP_DeviceRevision), scapy_all.XShortField("status", 0x0000), utils.XLEIntField("serial", 0x00000000), scapy_all.ByteField("product_name_length", 0), scapy_all.StrLenField("product_name", "", length_from=lambda p: p.product_name_length), scapy_all.XByteField("state", 0), ] def extract_padding(self, p): # print self.__class__.__name__ + ": P=" + str(p) return "", p
class CPF_Item(scapy_all.Packet): name = "CPF_Item" fields_desc = [ scapy_all.LEShortEnumField('type_id', 0, ITEM_ID_NUMBERS), scapy_all.LEShortField("length", None), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay
class ENIP_UDP_Item(scapy_all.Packet): name = "ENIP_UDP_Item" fields_desc = [ scapy_all.LEShortEnumField("type_id", 0, { 0x00b1: "Connected_Data_Item", 0x8002: "Sequenced_Address", }), scapy_all.LEShortField("length", None), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay
class ENIP_PACKET(scapy_all.Packet): """Ethernet/IP packet over TCP""" name = "ENIP_PACKET" fields_desc = [ scapy_all.LEShortEnumField("command_id", None, ENCAPSULATION_COMMANDS), scapy_all.LEShortField("length", None), utils.XLEIntField("session", 0), scapy_all.LEIntEnumField("status", 0, {0: "success"}), scapy_all.LELongField("sender_context", 0), scapy_all.LEIntField("options", 0), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay
class CPF_AddressDataItem(scapy_all.Packet): name = "CPF_AddressDataItem" fields_desc = [ scapy_all.LEShortEnumField( 'type_id', 0, { 0x0000: "Null Address", 0x00a1: "Connection-based Address", 0x00b1: "Connected Transport Packet", 0x00b2: "Unconnected Message", 0x0100: "ListServices response", 0x8002: 'Sequenced Address Item', }), scapy_all.LEShortField("length", None), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay