class CIP_ReqGetAttributeList(scapy_all.Packet): """The list of requested attributes in a CIP Get_Attribute_List request""" fields_desc = [ utils.LEShortLenField("count", None, count_of="attrs"), scapy_all.FieldListField("attrs", [], scapy_all.LEShortField("", 0), count_from=lambda pkt: pkt.count), ]
class SWAT_P1_RIO_DO(scapy_all.Packet): name = "SWAT_P1_RIO_DO" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.ByteField('number', 0), scapy_all.StrFixedLenField('reserved', 0, length=5), scapy_all.BitField('spare', 0, 4), scapy_all.BitEnumField('valve_close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('valve_open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('pump2_start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('pump1_start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.FieldListField( "spare2", [], scapy_all.ByteField('', 0), length_from=lambda p: p.underlayer.length - 9), ]
class CIP_PortSegment(scapy_all.Packet): name="CIP_PortSegment" PORT_IDENT={ 0: "Reserved", 1: "Back-Plane", 15: "Extended", } fields_desc = [ scapy_all.BitField("extended_link_address_size", 0, 1), scapy_all.BitEnumField("port_identifier", 0, 4, PORT_IDENT), scapy_all.ByteField("link_address_size", 0), scapy_all.ConditionalField( scapy_all.LEIntField("extended_port_identifier", 0), lambda p: p.port_identifier == 0xf # If the Port Identifier is 15, then a 16-bit field, called the Extended Port Identifier, shall be the next part of the Port Segment ), scapy_all.ConditionalField( scapy_all.FieldListField("Link_Address", [], scapy_all.XByteField("",0), length_from=lambda p: p.link_address_size ), lambda p: p.extended_link_address_size == 0x1 # If the Port Identifier is 15, then a 16-bit field, called the Extended Port Identifier, shall be the next part of the Port Segment ) ] def extract_padding(self, p): print self.__class__.__name__ + ": P=" + str(p) return "", p
class SWAT_P1_WRIO_AI(scapy_all.Packet): name = "SWAT_P1_WRIO_AI" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.LEIntField('padding', 0), scapy_all.LEShortField('level', 0), scapy_all.LEShortField('flow', 0), scapy_all.FieldListField( "spare", [], scapy_all.LEShortField("", 0), length_from=lambda p: p.underlayer.length - 10), ]
class CIP_MultipleServicePacket(scapy_all.Packet): """Multiple_Service_Packet request or response""" name = "CIP_MultipleServicePacket" fields_desc = [ utils.LEShortLenField("count", None, count_of="packets"), scapy_all.FieldListField("offsets", [], scapy_all.LEShortField("", 0), count_from=lambda pkt: pkt.count), # Assume the offsets are increasing, and no padding. FIXME: remove this assumption _CIPMSPPacketList("packets", [], CIP) ] def do_build(self): """Build the packet by concatenating packets and building the offsets list""" # Build the sub packets subpkts = [str(pkt) for pkt in self.packets] # Build the offset lists current_offset = 2 + 2 * len(subpkts) offsets = [] for p in subpkts: offsets.append(struct.pack("<H", current_offset)) current_offset += len(p) return struct.pack("<H", len(subpkts)) + "".join(offsets) + "".join(subpkts)