带有自定义图层的Scapy sr()

时间:2015-10-14 09:30:15

标签: python networking scapy bacnet

当使用sr()或srp()函数时 - Scapy如何知道收到的数据包是我发送的数据包的答案?

我编写了一个模仿BACNet的自定义协议。我可以将一个WHO_IS数据包发送到BACNet设备,并且该设备使用I_AM数据包进行应答,该数据包由于层绑定而被正确分解,但sr函数不会将其识别为答案。如何让Scapy接受这些数据包作为答案?

更新: 这就是我的图层类的样子。我认为answers()方法看起来不错,但它仍然不起作用。在实施self方法时,有什么我可能会误解的吗? 在我的理解中other指的是层本身的类,而other.payload是所讨论的接收数据包。因此,为了将有效负载传递到下一个更高层,我传递answers()并使用下一个更高层类调用Ether/IP/UDP/BVLC/NPDU/APDU方法。 这些图层的堆叠方式与class BVLC(Packet): name = "BVLC" fields_desc = [ # many fields ] def post_build(self, pkt, pay): if self.length == None: pkt = pkt[0:2] + struct.pack('!H', len(pay)+len(pkt)) + pkt[4:] return pkt+pay def answers(self, other): if not isinstance(other,BVLC): return 0 else: return NPDU.answers(other.payload) class NPDU(Packet): name = "NPDU" fields_desc = [ # again, many fields ] def answers(self, other): if not isinstance(other,NPDU): return 0 else: return APDU.answers(other.payload) class APDU(Packet): name = "APDU" fields_desc = [ # many fields and the only relevant field in this case ConditionalField( ByteEnumField( "serviceChoice", None, APDU_Service_Unconfirmed.revDict()), lambda pkt: pkt.pduType == APDU_Type.CONFIRMED_SERVICE_REQUEST or pkt.pduType == APDU_Type.UNCONFIRMED_SERVICE_REQUEST), ] def answers(self, other): if not isinstance(other,APDU): return 0 else: if self.serviceChoice == APDU_Service_Unconfirmed.WHO_IS and\ other.serviceChoice == APDU_Service_Unconfirmed.I_AM: return 1 return 0 相似。

uploads/text/file1.txt

1 个答案:

答案 0 :(得分:4)

Scapy sr只为每个已发送的数据包调用recv_packet.answers(sent_packet)。 因此,您必须为您的图层实施def answers(),请参阅:

def answers(self, other):
    """DEV: true if self is an answer from other"""
    if other.__class__ == self.__class__:
        return self.payload.answers(other.payload)
    return 0

以下是原始TCP图层的摘录:

def answers(self, other):
    if not isinstance(other, TCP):
        return 0
    if conf.checkIPsrc:
        if not ((self.sport == other.dport) and
                (self.dport == other.sport)):
            return 0
    if (abs(other.seq-self.ack) > 2+len(other.payload)):
        return 0
    return 1