scapy:无法将带有子键的字典传递给 ByteEnum 字段

scapy: Unable to pass dict with sub keys to ByteEnum Field

我已经为 scapy 中的 ByteEnum 字段创建了一个这样的字典。当我将此 _PCEP_ERR_values 字典传递给 ByteEnum 字段时,它出错了。回溯说不可散列类型字典。如何将带有子键的字典传递给 ByteEnumField?

这是我如何创建图层的片段:

_PCEP_ERR_types = {1: "PCEP session establishment failure",
                   3: "Unknown Object"}

_PCEP_ERR_values = {_PCEP_ERR_types[1]: {1: "Reception of an invalid Open message or a non Open message",
                                     2: "No Open message received before the expiration of the OpenWait timer",
                                     3: "Unacceptable and non-negotiable session characteristics",
                                     4: "Unacceptable but negotiable session characteristics",
                                     5: "Reception of a second Open message with still unacceptable session characteristics",
                                     6: "Reception of a PCErr message proposing unacceptable session characteristics",
                                     7: "No Keepalive or PCErr message received before the expiration of the KeepWait timer"},
                    _PCEP_ERR_types[3]: {1: "Unrecognized object class",
                                         2: "Unrecognized object Type"}}

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),
                      ByteEnumField("EV", 0, _PCEP_ERR_values)]

我执行脚本时回溯的片段:

Traceback (most recent call last):
  File "./pcep-v3.py", line 1624, in <module>
    class PCEPErrorObject(Packet):
  File "./pcep-v3.py", line 1635, in PCEPErrorObject
    ByteEnumField("EV", 0, _PCEP_ERR_values)]
  File "/usr/local/lib64/python2.6/site-packages/scapy/fields.py", line 771,
in __init__
    EnumField.__init__(self, name, default, enum, "B")
  File "/usr/local/lib64/python2.6/site-packages/scapy/fields.py", line 718,
in __init__
    s2i[enum[k]] = k
TypeError: unhashable type: 'dict'

这段代码没有按照您的想法进行。 _PCEP_ERR_values 应该将数值与字符串值相关联(就像 _PCEP_ERR_types),而您将文本值与字典相关联。

您必须使用 MultiEnumField,并且您在 Scapy source codeICMP 层中有一个使用该类型字段的绝佳示例。

_PCEP_ERR_types = {1: "PCEP session establishment failure",
                   3: "Unknown Object"}

_PCEP_ERR_values = {
    1: {1: "Reception of an invalid Open message or a non Open message",
        2: "No Open message received before the expiration of the OpenWait timer",
        3: "Unacceptable and non-negotiable session characteristics",
        4: "Unacceptable but negotiable session characteristics",
        5: "Reception of a second Open message with still unacceptable session characteristics",
        6: "Reception of a PCErr message proposing unacceptable session characteristics",
        7: "No Keepalive or PCErr message received before the expiration of the KeepWait timer"},
    3: {1: "Unrecognized object class",
        2: "Unrecognized object Type"}
}


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")]

顺便说一下(完全不相关)你应该看看 dispatch_hook Packet 来替换你的 common_object_header;这可能会为您节省访问公共字段值的不必要的间接访问(您可以使用 pkt.field_name 而不是 pkt.common_object_header.field_name