如何使用dispatch_hook()链接不同的图层。我有这样的包。我只是想知道是否有更好的方法使用dispatch_hook()。
这是我制作包的方式:
>>>> pkt=PCEPCommonHeader(Type=6)/PCEPErrorMsg(error_objects=[PCEPErrorObject()])
>>> pkt.show()
###[ PCEP common header ]###
Version= 1
Flags= 0
Type= PCEPErrorMsg
Length= None
###[ PCEPErrorMsg ]###
\error_objects\
|###[ PCEP-ERROR OBJECT ]###
| \common_object_header\
| |###[ PCEP Common Object Header ]###
| | oclass= PCEP-ERROR
| | oType= 1
| | resflags=
| | pflag=
| | iflag=
| | obLength= 4
| Reserved= 0
| flags= 0
| ET= 0
| EV= 0
>>>
Code Snip:
connection, pcc_address = pce.accept()
pcc_client=StreamSocket(connection,basecls=PCEPCommonHeader)
_PCEP_types = {6:"PCEPErrorMsg"}
_object_class = {13: "PCEP-ERROR"}
_PCEP_ERR_types = {3: "Unknown Object"}
_PCEP_ERR_values = {3: {1: "Unrecognized object class",
2: "Unrecognized object Type"}}
class PCEPCommonHeader(Packet):
"""This is the common header for all PCEP packets"""
name = "PCEP common header"
#Common Header Length is 4 bytes
fields_desc = [BitField("Version",1,3),
BitField("Flags",0,5),
ByteEnumField("Type", 2, _PCEP_types),
ShortField("Length", None)]
class PCEPCommonObjectHeader(Packet):
"""Common Header for the PCEP Objects"""
#Common ObjectHeader Length is 4 Bytes
name = "PCEP Common Object Header"
fields_desc = [ByteEnumField("oclass",0, _object_class),
BitField("oType",0,4),
FlagsField("resflags", 0x0, 2, "Res"),
FlagsField("pflag", 0x0, 1, "P"),
FlagsField("iflag", 0x0, 1, "I"),
ShortField("obLength", 4)]
class PCEPErrorObject(Packet):
'''PCEP-ERROR Object to notify error conditions in a PCEP session'''
name = 'PCEP-ERROR OBJECT'
common_object = PCEPCommonObjectHeader(oclass=13,oType=1)
fields_desc = [PacketField("common_object_header",common_object,PCEPCommonObjectHeader),
ByteField("Reserved",0),
ByteField("flags",0),
ByteEnumField("ET", 0, _PCEP_ERR_types),
MultiEnumField("EV", 0, _PCEP_ERR_values,depends_on=lambda pkt: pkt.ET,fmt="B")]
class PCEPErrorMsg(Packet):
fields_desc = [PacketListField("error_objects",None,PCEPErrorObject)]
bind_layers( PCEPCommonHeader, PCEPErrorMsg, Type=6)
答案 0 :(得分:1)
.dispatch_hook()
背后的想法是拥有一个主类,让我们称之为Protocol
继承(直接或不是)来自Packet
,并拥有派生类(直接继承)或不,来自Protocol
或Packet
);假设我们有Protocol1
和Protocol2
。
当您(或Scapy)通过调用.dispatch_hook()
实例化该类时,将调用Protocol()
方法。它使用与传递给Protocol()
完全相同的参数调用,并返回将要(真正)使用的类。
让我们从Scapy代码中得到一个真实的例子。 Ether()
(以太网v2)和Dot3()
()是非常相似的第二层协议:两者都以六字节目标地址开头,后跟六字节源地址。 Ether()
接下来的两个字节是有效载荷的类型,而Dot3()
接下来的两个字节是数据包大小。由于数据包不能超过1500字节,并且以太网类型不能小于1500(1536是最小的精确值)。
来自Scapy代码(文件scapy/layers/l2.py
):
class Ether(Packet):
[...]
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 14:
if struct.unpack("!H", _pkt[12:14])[0] <= 1500:
return Dot3
return cls
class Dot3(Packet):
[...]
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 14:
if struct.unpack("!H", _pkt[12:14])[0] > 1500:
return Ether
return cls
如果需要,可以找到一个更复杂,更完整的示例in TorPylle,即Scapy中TOR协议的实现。