class SCION(scapy.Packet): name = 'SCION' fields_desc = [ # Common header scapy.BitField('version', 0, 4), scapy.BitEnumField('dst_type', "ipv4", 6, SCION_ADDR_TYPE), scapy.BitEnumField('src_type', "ipv4", 6, SCION_ADDR_TYPE), scapy.BitField('total_len', None, 16), scapy.BitField('hdr_len', None, 8), scapy.BitField('curr_inf', None, 8), scapy.BitField('curr_hf', None, 8), scapy.BitEnumField('next_hdr', None, 8, scapy.IP_PROTOS), scapy.PacketField('addr', None, SCIONAddr), scapy.PacketListField('path', None, PathSegment, count_from=lambda _: 3), scapy.PacketField('ext', None, SecurityExtension) ] # this is terrible, but apparently that's how scapy works :-/ def post_build(self, pkt, pay): # compute lengths if self.total_len == None: self.total_len = len(pkt) + len(pay) pkt = pkt[:2] + struct.pack('!H', self.total_len) + pkt[4:] if self.hdr_len == None: self.hdr_len = len(pkt) - self.ext.hdr_len if self.hdr_len % 8 != 0: raise ValueError( "SCION packet header length not multiple of 8 bytes!") self.hdr_len = int(self.hdr_len / 8) #must divide by 8 pkt = pkt[:4] + struct.pack('B', self.hdr_len) + pkt[5:] return pkt + 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 CIP_ReqForwardOpen(scapy_all.Packet): """Forward Open request""" name = "CIP_ReqForwardOpen" fields_desc = [ scapy_all.BitField("priority", 0, 4), scapy_all.BitField("tick_time", 0, 4), scapy_all.ByteField("timeout_ticks", 249), scapy_all.LEIntField("OT_network_connection_id", 0x80000031), scapy_all.LEIntField("TO_network_connection_id", 0x80fe0030), scapy_all.LEShortField("connection_serial_number", 0x1337), scapy_all.LEShortField("vendor_id", 0x004d), scapy_all.LEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("connection_timeout_multiplier", 0), scapy_all.X3BytesField("reserved", 0), scapy_all.LEIntField("OT_rpi", 0x007a1200), # 8000 ms scapy_all.PacketField('OT_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.LEIntField("TO_rpi", 0x007a1200), scapy_all.PacketField('TO_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.XByteField( "transport_type", 0xa3), # direction server, application object, class 3 scapy_all.ByteField("path_wordsize", None), CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]
class SCIONAddr(scapy.Packet): name = 'SCION Address header' fields_desc = [ scapy.PacketField('dst_isdas', None, ISD_AS), scapy.PacketField('src_isdas', None, ISD_AS), # hard-coded v4 for now scapy.IPField('dst_host', None), scapy.IPField('src_host', None), ] def extract_padding(self, p): # TODO fix when removing hard-coded v4 return "", p
class ENIP_SendUnitData(scapy_all.Packet): """Data in ENIP header specific to the specified command""" name = "ENIP_SendUnitData" fields_desc = [ scapy_all.LEIntField("interface_handle", 0), scapy_all.LEShortField("timeout", 0), scapy_all.PacketField("Encapsulated_CPF_packet", enip_cpf.ENIP_CPF(), enip_cpf.ENIP_CPF), # utils.LEShortLenField("count", None, count_of="items"), # scapy_all.PacketListField("items", [], ENIP_SendUnitData_Item, # count_from=lambda p: p.count), ]
class CIP_ReqForwardOpen(scapy_all.Packet): """Forward Open request""" name = "CIP_ReqForwardOpen" SEGMENT_TYPE = { 0x00: "Port Segment", 0x01: "Logical Segment", 0x02: "Network Segment", 0x03: "Symbolic Segment", 0x04: "Data Segment", 0x05: "Data Type (constructed)", 0x06: "Data Type (elementary)", 0x07: "Reserved for future use", } fields_desc = [ # Updated a few field descriptions to adjust how they are displayed # Altered fields begin with utils. rather than scapy_all. - MED scapy_all.BitField("priority", 0, 4), scapy_all.BitField("tick_time", 0, 4), scapy_all.ByteField("timeout_ticks", 249), utils.XLEIntField("OT_network_connection_id", 0x80000031), utils.XLEIntField("TO_network_connection_id", 0x80fe0030), scapy_all.LEShortField("connection_serial_number", 0x1337), utils.XLEShortField("vendor_id", 0x004d), utils.XLEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("connection_timeout_multiplier", 0), scapy_all.X3BytesField("reserved", 0), utils.XLEIntField("OT_rpi", 0x007a1200), # 8000 ms scapy_all.PacketField('OT_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), utils.XLEIntField("TO_rpi", 0x007a1200), scapy_all.PacketField('TO_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.XByteField("transport_type", 0xa3), # direction server, application object, class 3 # Changed name - MED scapy_all.ByteField("Connection_Path_Size", None), #The number of 16 bit words in the Connection_Path field. # scapy_all.PacketListField("path_segment_items", [], CIP_Path1, length_from=lambda p: 2 * p.Connection_Path_Size), # Modified Implementation - MED scapy_all.PacketListField("path_segment_items", [], CIP_PathPadded, length_from=lambda p: 6), # CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]