使用 dispatch_hook()
Using dispatch_hook()
如何使用 dispatch_hook() link 不同的图层。我有这样的包裹。我只是想知道是否有更好的方法使用 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
>>>
代码片段:
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)
.dispatch_hook()
背后的想法是有一个主要的 class,我们称它为 Protocol
,它继承(直接或不直接)自 Packet
,并派生classes(直接或不直接继承自 Protocol
或 Packet
);假设我们有 Protocol1
和 Protocol2
.
当您(或 Scapy)通过调用 Protocol()
实例化 class 时,将调用 .dispatch_hook()
方法。它使用与您传递给 Protocol()
和 returns 将(真正)使用的 class 完全相同的参数调用。
让我们举一个真实的例子,来自Scapy代码。 Ether()
(Ethernet 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 协议的实现。
如何使用 dispatch_hook() link 不同的图层。我有这样的包裹。我只是想知道是否有更好的方法使用 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
>>>
代码片段:
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)
.dispatch_hook()
背后的想法是有一个主要的 class,我们称它为 Protocol
,它继承(直接或不直接)自 Packet
,并派生classes(直接或不直接继承自 Protocol
或 Packet
);假设我们有 Protocol1
和 Protocol2
.
当您(或 Scapy)通过调用 Protocol()
实例化 class 时,将调用 .dispatch_hook()
方法。它使用与您传递给 Protocol()
和 returns 将(真正)使用的 class 完全相同的参数调用。
让我们举一个真实的例子,来自Scapy代码。 Ether()
(Ethernet 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 协议的实现。