def i2h(self, pkt, x): if x is None: try: x = conf.neighbor.resolve(pkt, pkt.payload) except socket.error: pass if x is None: x = "ff:ff:ff:ff:ff:ff" warning("Mac address to reach destination not found. Using broadcast.") # noqa: E501 return MACField.i2h(self, pkt, x)
def i2h(self, pkt, x): if x is None: iff = self.getif(pkt) if iff is None: iff = conf.iface if iff: try: x = get_if_hwaddr(iff) except: pass if x is None: x = "00:00:00:00:00:00" return MACField.i2h(self, pkt, x)
def i2h(self, pkt, x): if x is None: iff = self.getif(pkt) if iff is None: iff = conf.iface if iff: try: x = get_if_hwaddr(iff) except Exception as e: warning("Could not get the source MAC: %s" % e) if x is None: x = "00:00:00:00:00:00" return MACField.i2h(self, pkt, x)
class ARP(Packet): name = "ARP" fields_desc = [ XShortField("hwtype", 0x0001), XShortEnumField("ptype", 0x0800, ETHER_TYPES), FieldLenField("hwlen", None, fmt="B", length_of="hwsrc"), FieldLenField("plen", None, fmt="B", length_of="psrc"), ShortEnumField( "op", 1, { "who-has": 1, "is-at": 2, "RARP-req": 3, "RARP-rep": 4, "Dyn-RARP-req": 5, "Dyn-RAR-rep": 6, "Dyn-RARP-err": 7, "InARP-req": 8, "InARP-rep": 9 }), MultipleTypeField( [ (ARPSourceMACField("hwsrc"), (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6, lambda pkt, val: pkt.hwtype == 1 and (pkt.hwlen == 6 or (pkt.hwlen is None and (val is None or len(val) == 6 or valid_mac(val)))))), ], StrFixedLenField("hwsrc", None, length_from=lambda pkt: pkt.hwlen), ), MultipleTypeField( [ (SourceIPField("psrc", "pdst"), (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4, lambda pkt, val: pkt.ptype == 0x0800 and (pkt.plen == 4 or (pkt.plen is None and (val is None or valid_net(val)))))), (SourceIP6Field("psrc", "pdst"), (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16, lambda pkt, val: pkt.ptype == 0x86dd and (pkt.plen == 16 or (pkt.plen is None and (val is None or valid_net6(val)))))), ], StrFixedLenField("psrc", None, length_from=lambda pkt: pkt.plen), ), MultipleTypeField( [ (MACField("hwdst", ETHER_ANY), (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6, lambda pkt, val: pkt.hwtype == 1 and (pkt.hwlen == 6 or (pkt.hwlen is None and (val is None or len(val) == 6 or valid_mac(val)))))), ], StrFixedLenField("hwdst", None, length_from=lambda pkt: pkt.hwlen), ), MultipleTypeField( [ (IPField("pdst", "0.0.0.0"), (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4, lambda pkt, val: pkt.ptype == 0x0800 and (pkt.plen == 4 or (pkt.plen is None and (val is None or valid_net(val)))))), (IP6Field("pdst", "::"), (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16, lambda pkt, val: pkt.ptype == 0x86dd and (pkt.plen == 16 or (pkt.plen is None and (val is None or valid_net6(val)))))), ], StrFixedLenField("pdst", None, length_from=lambda pkt: pkt.plen), ), ] def hashret(self): return struct.pack(">HHH", self.hwtype, self.ptype, ((self.op + 1) // 2)) + self.payload.hashret() def answers(self, other): if not isinstance(other, ARP): return False if self.op != other.op + 1: return False # We use a loose comparison on psrc vs pdst to catch answers # with ARP leaks self_psrc = self.get_field('psrc').i2m(self, self.psrc) other_pdst = other.get_field('pdst').i2m(other, other.pdst) return self_psrc[:len(other_pdst)] == other_pdst[:len(self_psrc)] def route(self): dst = self.pdst if isinstance(dst, Gen): dst = next(iter(dst)) return conf.route.route(dst) def extract_padding(self, s): return "", s def mysummary(self): if self.op == 1: return self.sprintf("ARP who has %pdst% says %psrc%") if self.op == 2: return self.sprintf("ARP is at %hwsrc% says %psrc%") return self.sprintf("ARP %op% %psrc% > %pdst%")
def i2m(self, pkt, x): return MACField.i2m(self, pkt, self.i2h(pkt, x))
def __init__(self, name, getif=None): MACField.__init__(self, name, None) self.getif = ((lambda pkt: pkt.payload.route()[0]) if getif is None else getif)
def __init__(self, name): MACField.__init__(self, name, None)
class OFPATSetDlDst(OpenFlow): name = "OFPAT_SET_DL_DST" fields_desc = [ShortEnumField("type", 5, ofp_action_types), ShortField("len", 16), MACField("dl_addr", "0"), XBitField("pad", 0, 48)]
class LLTD(Packet): name = "LLTD" answer_hashret = { # (tos, function) tuple mapping (answer -> query), used by # .hashret() (1, 1): (0, 0), (0, 12): (0, 11), } fields_desc = [ ByteField("version", 1), ByteEnumField("tos", 0, { 0: "Topology discovery", 1: "Quick discovery", 2: "QoS diagnostics", }), ByteField("reserved", 0), MultiEnumField("function", 0, { 0: { 0: "Discover", 1: "Hello", 2: "Emit", 3: "Train", 4: "Probe", 5: "Ack", 6: "Query", 7: "QueryResp", 8: "Reset", 9: "Charge", 10: "Flat", 11: "QueryLargeTlv", 12: "QueryLargeTlvResp", }, 1: { 0: "Discover", 1: "Hello", 8: "Reset", }, 2: { 0: "QosInitializeSink", 1: "QosReady", 2: "QosProbe", 3: "QosQuery", 4: "QosQueryResp", 5: "QosReset", 6: "QosError", 7: "QosAck", 8: "QosCounterSnapshot", 9: "QosCounterResult", 10: "QosCounterLease", }, }, depends_on=lambda pkt: pkt.tos, fmt="B"), MACField("real_dst", None), MACField("real_src", None), ConditionalField(ShortField("xid", 0), lambda pkt: pkt.function in [0, 8]), ConditionalField(ShortField("seq", 0), lambda pkt: pkt.function not in [0, 8]), ] def post_build(self, pkt, pay): if (self.real_dst is None or self.real_src is None) and \ isinstance(self.underlayer, Ether): eth = self.underlayer if self.real_dst is None: pkt = (pkt[:4] + eth.fields_desc[0].i2m(eth, eth.dst) + pkt[10:]) if self.real_src is None: pkt = (pkt[:10] + eth.fields_desc[1].i2m(eth, eth.src) + pkt[16:]) return pkt + pay def mysummary(self): if isinstance(self.underlayer, Ether): return self.underlayer.sprintf( 'LLTD %src% > %dst% %LLTD.tos% - %LLTD.function%') else: return self.sprintf('LLTD %tos% - %function%') def hashret(self): tos, function = self.tos, self.function return "%c%c" % self.answer_hashret.get((tos, function), (tos, function)) def answers(self, other): if not isinstance(other, LLTD): return False if self.tos == 0: if self.function == 0 and isinstance(self.payload, LLTDDiscover) \ and len(self[LLTDDiscover].stations_list) == 1: # "Topology discovery - Discover" with one MAC address # discovered answers a "Quick discovery - Hello" return other.tos == 1 and \ other.function == 1 and \ LLTDAttributeHostID in other and \ other[LLTDAttributeHostID].mac == \ self[LLTDDiscover].stations_list[0] elif self.function == 12: # "Topology discovery - QueryLargeTlvResp" answers # "Topology discovery - QueryLargeTlv" with same .seq # value return other.tos == 0 and other.function == 11 \ and other.seq == self.seq elif self.tos == 1: if self.function == 1 and isinstance(self.payload, LLTDHello): # "Quick discovery - Hello" answers a "Topology # discovery - Discover" return other.tos == 0 and other.function == 0 and \ other.real_src == self.current_mapper_address return False
class OFPMatch(Packet): name = "OFP_MATCH" fields_desc = [ FlagsField("wildcards1", None, 12, ["DL_VLAN_PCP", "NW_TOS"]), BitField("nw_dst_mask", None, 6), BitField("nw_src_mask", None, 6), FlagsField("wildcards2", None, 8, [ "IN_PORT", "DL_VLAN", "DL_SRC", "DL_DST", "DL_TYPE", "NW_PROTO", "TP_SRC", "TP_DST" ]), ShortEnumField("in_port", None, ofp_port_no), MACField("dl_src", None), MACField("dl_dst", None), ShortField("dl_vlan", None), ByteField("dl_vlan_pcp", None), XByteField("pad1", None), ShortField("dl_type", None), ByteField("nw_tos", None), ByteField("nw_proto", None), XShortField("pad2", None), IPField("nw_src", "0"), IPField("nw_dst", "0"), ShortField("tp_src", None), ShortField("tp_dst", None) ] def extract_padding(self, s): return b"", s # with post_build we create the wildcards field bit by bit def post_build(self, p, pay): # first 10 bits of an ofp_match are always set to 0 lst_bits = "0" * 10 # when one field has not been declared, it is assumed to be wildcarded if self.wildcards1 is None: if self.nw_tos is None: lst_bits += "1" else: lst_bits += "0" if self.dl_vlan_pcp is None: lst_bits += "1" else: lst_bits += "0" else: w1 = binrepr(self.wildcards1) lst_bits += "0" * (2 - len(w1)) lst_bits += w1 # ip masks use 6 bits each if self.nw_dst_mask is None: if self.nw_dst == "0": lst_bits += "111111" # 0x100000 would be ok too (32-bit IP mask) else: lst_bits += "0" * 6 else: m1 = binrepr(self.nw_dst_mask) lst_bits += "0" * (6 - len(m1)) lst_bits += m1 if self.nw_src_mask is None: if self.nw_src == "0": lst_bits += "111111" else: lst_bits += "0" * 6 else: m2 = binrepr(self.nw_src_mask) lst_bits += "0" * (6 - len(m2)) lst_bits += m2 # wildcards2 works the same way as wildcards1 if self.wildcards2 is None: if self.tp_dst is None: lst_bits += "1" else: lst_bits += "0" if self.tp_src is None: lst_bits += "1" else: lst_bits += "0" if self.nw_proto is None: lst_bits += "1" else: lst_bits += "0" if self.dl_type is None: lst_bits += "1" else: lst_bits += "0" if self.dl_dst is None: lst_bits += "1" else: lst_bits += "0" if self.dl_src is None: lst_bits += "1" else: lst_bits += "0" if self.dl_vlan is None: lst_bits += "1" else: lst_bits += "0" if self.in_port is None: lst_bits += "1" else: lst_bits += "0" else: w2 = binrepr(self.wildcards2) lst_bits += "0" * (8 - len(w2)) lst_bits += w2 # In order to write OFPMatch compliant with the specifications, # if prereq_autocomplete has been set to True # we assume ethertype=IP or nwproto=TCP when appropriate subfields are provided. # noqa: E501 if conf.contribs['OPENFLOW']['prereq_autocomplete']: if self.dl_type is None: if self.nw_src != "0" or self.nw_dst != "0" or \ self.nw_proto is not None or self.nw_tos is not None: p = p[:22] + struct.pack("!H", 0x0800) + p[24:] lst_bits = lst_bits[:-5] + "0" + lst_bits[-4:] if self.nw_proto is None: if self.tp_src is not None or self.tp_dst is not None: p = p[:22] + struct.pack("!H", 0x0800) + p[24:] lst_bits = lst_bits[:-5] + "0" + lst_bits[-4:] p = p[:25] + struct.pack("!B", 0x06) + p[26:] lst_bits = lst_bits[:-6] + "0" + lst_bits[-5:] ins = b"".join( chb(int("".join(x), 2)) for x in zip(*[iter(lst_bits)] * 8)) # noqa: E501 p = ins + p[4:] return p + pay
class ISIS_IsNeighbourTlv(ISIS_GenericTlv): name = "ISIS IS Neighbour TLV" fields_desc = [ByteEnumField("type", 6, _isis_tlv_names), FieldLenField("len", None, length_of= "neighbours", fmt="B"), FieldListField("neighbours", [], MACField("", "00.00.00.00.00.00"), count_from= lambda pkt: pkt.len / 6)]
def __init__(self, name, default, resolve=False): MACField.__init__(self, name, default) if resolve: conf.resolve.add(self)
class ProfinetDCP(Packet): """ Profinet DCP Packet Requests are handled via ConditionalField because here only 1 Block is used qevery time Ŕesoinse can contain 1..n Blocks, for that you have to use one ProfinetDCP Layer with one or multiple DCP*Block Layers ProfinetDCP / DCPNameOfStationBlock / DCPDeviceIDBlock ... Example for a DCP Identify All Request: Ether(dst="01:0e:cf:00:00:00") / 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) Example for a DCP Identify Response: Ether(dst=dst_mac) / ProfinetIO(frameID=DCP_IDENTIFY_RESPONSE_FRAME_ID) / ProfinetDCP( service_id=DCP_SERVICE_ID_IDENTIFY, service_type=DCP_RESPONSE) / DCPNameOfStationBlock(name_of_station="device1") Example for a DCP Set Request: Ether(dst=mac) / ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST, option=2, sub_option=2, dcp_data_length=14, dcp_block_length=10, name_of_station=name, reserved=0) """ name = "Profinet DCP" # a DCP PDU consists of some fields and 1..n DCP Blocks fields_desc = [ ByteEnumField("service_id", 5, DCP_SERVICE_ID), ByteEnumField("service_type", 0, DCP_SERVICE_TYPE), XIntField("xid", 0x01000001), # XShortField('reserved', 0), ShortField('reserved', 0), LenField("dcp_data_length", None), # DCP REQUEST specific ConditionalField(ByteEnumField("option", 2, DCP_OPTIONS), lambda pkt: pkt.service_type == 0), ConditionalField( MultiEnumField("sub_option", 3, DCP_SUBOPTIONS, fmt='B', depends_on=lambda p: p.option), lambda pkt: pkt.service_type == 0), # calculate the len fields - workaround ConditionalField(LenField("dcp_block_length", 0), lambda pkt: pkt.service_type == 0), # DCP SET REQUEST # ConditionalField( ShortEnumField("block_qualifier", 1, BLOCK_QUALIFIERS), lambda pkt: pkt.service_id == 4 and pkt.service_type == 0), # Name Of Station ConditionalField( StrLenField("name_of_station", "et200sp", length_from=lambda x: x.dcp_block_length - 2), lambda pkt: pkt.service_id == 4 and pkt.service_type == 0 and pkt. option == 2 and pkt.sub_option == 2), # MAC ConditionalField( MACField("mac", "00:00:00:00:00:00"), lambda pkt: pkt.service_id == 4 and pkt.service_type == 0 and pkt.option == 1 and pkt.sub_option == 1), # IP ConditionalField( IPField("ip", "192.168.0.2"), lambda pkt: pkt.service_id == 4 and pkt.service_type == 0 and pkt.option == 1 and pkt.sub_option == 2), ConditionalField( IPField("netmask", "255.255.255.0"), lambda pkt: pkt.service_id == 4 and pkt. service_type == 0 and pkt.option == 1 and pkt.sub_option == 2), ConditionalField( IPField("gateway", "192.168.0.1"), lambda pkt: pkt.service_id == 4 and pkt. service_type == 0 and pkt.option == 1 and pkt.sub_option == 2), # DCP IDENTIFY REQUEST # # Name of station ConditionalField( StrLenField("name_of_station", "et200sp", length_from=lambda x: x.dcp_block_length), lambda pkt: pkt.service_id == 5 and pkt.service_type == 0 and pkt. option == 2 and pkt.sub_option == 2), # Alias name ConditionalField( StrLenField("alias_name", "et200sp", length_from=lambda x: x.dcp_block_length), lambda pkt: pkt.service_id == 5 and pkt.service_type == 0 and pkt. option == 2 and pkt.sub_option == 6), # implement further REQUEST fields if needed .... # DCP RESPONSE BLOCKS # ConditionalField( PacketListField("dcp_blocks", [], guess_dcp_block_class, length_from=lambda p: p.dcp_data_length), lambda pkt: pkt.service_type == 1), ] def post_build(self, pkt, pay): # add padding to ensure min packet length padding = MIN_PACKET_LENGTH - (len(pkt + pay)) pay += b"\0" * padding return Packet.post_build(self, pkt, pay)
class IfacePowerChangeStatus_Entry(Packet): name = "Interface Entry" fields_desc = [MACField("mac", None), XByteField("power_state", None)] def extract_padding(self, s): return "", s
class PAS5211MsgSwitchToInboundMode(PAS5211Msg): opcode = 0xec name = "PAS5211MsgSwitchToInboundMode" fields_desc = [MACField("mac", None), LEShortField("mode", 0)]
def __init__(self, name): # type: (str) -> None MACField.__init__(self, name, None)
def __init__(self, name, getif=None): # type: (str, Optional[Any]) -> None MACField.__init__(self, name, None) self.getif = (lambda pkt: pkt.route()[0]) if getif is None else getif
def i2m(self, pkt, x): # type: (Optional[Ether], Optional[Any]) -> bytes return MACField.i2m(self, pkt, self.i2h(pkt, x))